source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/USANS/LakeDesmearing_JB.ipf @ 651

Last change on this file since 651 was 624, checked in by ajj, 13 years ago

Implement XML writing in USANS reduction

  • Property eol-style set to native
File size: 52.7 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma Version=2.20
3#pragma IgorVersion=6.1
4
5//////////////////////////////////////////////
6// Igor conversion:     03 FEB 06 SRK
7//                      Revision:       03 MAR 06 SRK
8//
9//      Program uses Lake's iterative technique, J. A. Lake, Acta Cryst. 23 (1967) 191-4.
10//      to DESMEAR Infinite slit smeared USANS DATA.
11//
12//      TO SEE DESCRIPTION, CHECK COMPUTER SOFTWARE LOGBOOK, P13,41-46, 50
13//      J. BARKER, August, 2001
14//      Switches from fast to slow convergence near target chi JGB 2/2003
15//
16// steps are:
17// load
18// mask
19// extrapolate (find the power law of the desmeared set = smeared -1)
20// smooth (optional)
21// desmear based on dQv and chi^2 target
22// save result
23//
24/////////
25// Waves produced at each step: (Q/I/S with the following extensions)
26//
27// Load:                Uses -> nothing (Kills old waves)
28//                              Produces -> "_exp" and "_exp_orig"
29//
30// Mask:                Uses -> "_exp"
31//                              Produces -> "_msk"
32//
33// Extrapolate: Uses -> nothing
34//                                      Produces -> nothing
35//
36// Smooth:      Uses -> "_smth" OR "_msk" OR "_exp" (in that order)
37//                              Produces -> "_smth"
38//
39// Desmear:     Uses ->  "_smth" OR "_msk" OR "_exp" (in that order)
40//                              Produces -> "_dsm"
41//
42////////
43
44///***** TO FIX *******
45// - ? power law + background extrapolation (only useful for X-ray data...)
46//
47// see commented code lines for Igor 4 or Igor 5
48// - there are only a few options and calls that are not Igor 4 compatible.
49// Igor 4 routines are currently used.
50
51////////////////////////////////////////////////////////////////////////
52
53// main entry routine
54Proc Desmear()
55
56        String USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
57
58        //check for the correct data folder, initialize if necessary
59        //
60        if(DataFolderExists(USANSFolder+":DSM") == 0)
61                Execute "Init_Desmearing()"
62        endif
63       
64        SetDataFolder $(USANSFolder+":DSM")
65        //always initialize these global variables
66        gStr1 = ""
67        gStr2 = ""
68        gIterStr = ""
69        SetDataFolder root:
70       
71        DoWindow/F Desmear_Graph
72        if(V_flag==0)
73                Execute "Desmear_Graph()"
74        endif
75End
76
77Proc Init_Desmearing()
78
79        String USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
80
81        //set up the folder(s) needed
82        NewDataFolder/O $(USANSFolder+":DSM")
83        NewDataFolder/O $(USANSFolder+":myGlobals")             //in case it wasn't created elsewhere
84       
85        SetDataFolder $(USANSFolder+":DSM")
86       
87        String/G gCurFile=""
88       
89        Variable/G gMaxFastIter = 100                   //max number of iter in Fast convergence
90        Variable/G gMaxSlowIter = 10000
91       
92        Variable/G gNptsExtrap = 10             //points for high q extrapolation
93        Variable/G gChi2Target = 1              //chi^2 target
94        Variable/G gPowerM = -4
95        Variable/G gDqv = 0.117                 //2005 measured slit height - see John
96        Variable/G gNq = 1
97        Variable/G gS = 0               // global varaible for Midpnt()
98        Variable/G gSmoothFac=0.03
99       
100        Variable/G gChi2Final = 0               //chi^2 final
101        Variable/G gIterations = 0              //total number of iterations
102       
103        String/G gStr1 = ""                             //information strings
104        String/G gStr2 = ""
105        String/G gIterStr = ""
106        Variable/G gChi2Smooth = 0
107       
108        Variable/G gFreshMask=1
109       
110        SetDataFolder root:
111End
112
113//////////// Lake desmearing routines
114
115//      Smears guess Y --> YS using weighting array
116Function DSM_Smear(Y_wave,Ys,NQ,FW)
117        Wave Y_wave,Ys
118        Variable nq
119        Wave FW
120       
121        Variable ii,jj,summ
122        for(ii=0;ii<nq;ii+=1)
123                summ=0
124                for(jj=0;jj<nq;jj+=1)
125                        summ = summ + Y_wave[jj]*FW[ii][jj]
126                endfor
127                Ys[ii] = summ
128        endfor
129       
130        Return (0)
131End
132
133//      CALCULATES CHI^2
134FUNCTION CHI2(ys_new,ys_exp,w,NQ)
135        Wave ys_new,ys_exp,w
136        Variable nq
137
138        Variable CHI2,summ,ii
139
140        SUMm = 0.0
141        for(ii=0;ii<nq;ii+=1)
142//              if(numtype(YS_EXP[ii]) == 0 && numtype(YS_NEW[ii]) == 0)
143                SUMm=SUMm+W[ii]*(YS_EXP[ii]-YS_NEW[ii])^2
144//              endif
145        endfor
146       
147        CHI2=SUMm/(NQ-1)
148       
149        RETURN CHI2
150END
151
152//      Routine calculates the weights needed to convert a table
153//      representation of a scattering function I(q) into the infinite
154//      slit smeared table represented as Is(q)
155//      Is(qi) = Sum(j=i-n) Wij*I(qj)
156//      Program assumes data is extrapolated from qn to dqv using powerlaw
157//      I(q) = Aq^m
158//      Required input:
159//      N       : Number of data points {in Global common block }
160//      q(N)    : Array of q values     {in Global common block }
161//      dqv     : Limit of slit length  {in Global common block }
162//      m       : powerlaw for extrapolation.
163//
164//      Routine output:
165//      W(N,N)  : Weights array
166//
167//      The weights obtained from this routine can be used to calculate
168//      Is(q) for any I(q) function.
169//
170//      Calculation based upon linear interpolation between points.
171//      See p.44, Computer Software Log book.
172//      11/00 JGB
173Function Weights_L(m,FW,Q_exp)          //changed input w to FW (FW is two dimensional)
174        Variable m
175        Wave FW,Q_exp
176
177        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
178       
179        NVAR dqv = $(USANSFolder+":DSM:gDqv")
180        NVAR NN = $(USANSFolder+":DSM:gNq")
181
182//      Calculate Remainder fractions and put into separate array.
183        Variable lower,ii,ss,jj
184        Duplicate/O Q_exp $(USANSFolder+":DSM:R_wave")
185        wave r_wave = $(USANSFolder+":DSM:R_wave")
186       
187//      Make/O/D/N=75 root:DSM:SS_save  //debug
188//      wave SS_save = root:DSM:SS_save
189       
190        Print "calculating remainders by integration..."
191        for(ii=0;ii<NN-1;ii+=1)
192                lower = sqrt(Q_exp[NN-1]^2-Q_exp[ii]^2)
193                ss = Qromo(lower,dqv,Q_exp[ii],m)               //new parameter list for Qromo call
194//              SS_save[ii] = ss
195                R_wave[ii] = (Q_exp[NN-1]^(-m)/dqv)*SS
196//              Printf "I = %d R_wave[ii] =%g\r",ii,R_wave[ii]
197        endfor
198       
199        lower = 0.0
200        ss = Qromo(lower,dqv,Q_exp[NN-1],m)             //new parameter list for Qromo call
201        R_wave[NN-1] = (Q_exp[NN-1]^(-m)/dqv)*SS
202//      Printf "I = %d R_wave[ii] =%g\r",NN-1,R_wave[NN-1]
203//      SS_save[ii] = ss
204
205//      Make/O/D/N=(75,75) root:DSM:IG_save             //debug
206//      wave IG_save=root:DSM:IG_save
207       
208//      Zero weight matrix... then fill it
209        FW = 0
210        Print "calculating full weights...."
211//      Calculate weights
212        for(ii=0;ii<NN;ii+=1)
213                for(jj=ii+1;jj<NN-1;jj+=1)
214                        FW[ii][jj] = DU(ii,jj)*(1.0+Q_exp[jj]/(Q_exp[jj+1]-Q_exp[jj]))
215                        FW[ii][jj] -= (1.0/(Q_exp[jj+1]-Q_exp[jj]))*IG(ii,jj)
216                        FW[ii][jj] -= DU(ii,jj-1)*Q_exp[jj-1]/(Q_exp[jj]-Q_exp[jj-1])
217                        FW[ii][jj] += (1.0/(Q_exp[jj]-Q_exp[jj-1]))*IG(ii,jj-1)
218                        FW[ii][jj] *= (1.0/dqv)                 
219//              Printf "FW[%d][%d] = %g\r",ii,jj,FW[ii][jj]
220                endfor
221        endfor
222//
223//      special case: I=J,I=N
224        for(ii=0;ii<NN-1;ii+=1)
225                FW[ii][ii] = DU(ii,ii)*(1.0+Q_exp[ii]/(Q_exp[ii+1]-Q_exp[ii]))
226                FW[ii][ii] -= (1.0/(Q_exp[ii+1]-Q_exp[ii]))*IG(ii,ii)
227                FW[ii][ii] *= (1.0/dqv)
228//              Printf "FW[%d][%d] = %g\r",ii,jj,FW[ii][jj]
229//     following line corrected for N -> NN-1 since Igor indexes from 0! (Q_exp[NN] DNE!)
230                FW[ii][NN-1] = -DU(ii,NN-2)*Q_exp[NN-2]/(Q_exp[NN-1]-Q_exp[NN-2])
231                FW[ii][NN-1] += (1.0/(Q_exp[NN-1]-Q_exp[NN-2]))*IG(ii,NN-2)
232                FW[ii][NN-1] *= (1.0/dqv)
233                FW[ii][NN-1] += R_wave[ii]
234//              Printf "FW[%d][%d] = %g\r",ii,NN-1,FW[ii][NN-1]
235        endfor
236//
237//      special case: I=J=N
238        FW[NN-1][NN-1] = R_wave[NN-1]
239//
240        Return (0)
241End
242
243////
244Function Integrand_dsm(u,qi,m)
245        Variable u,qi,m
246       
247        Variable integrand
248        Integrand = (u^2+qi^2)^(m/2)
249        return integrand
250end
251
252///
253Function DU(ii,jj)
254        Variable ii,jj
255
256        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
257       
258        Wave Q_exp = $(USANSFolder+":DSM:Q_exp")
259        Variable DU
260
261//      Wave DU_save=root:DSM:DU_save
262        If (ii == jj)
263          DU = sqrt(Q_exp[jj+1]^2-Q_exp[ii]^2)
264        Else
265          DU = sqrt(Q_exp[jj+1]^2-Q_exp[ii]^2) - sqrt(Q_exp[jj]^2-Q_exp[ii]^2)
266        EndIf
267       
268//      DU_save[ii][jj] = DU
269        Return DU
270End
271
272Function IG(ii,jj)
273        Variable ii,jj
274       
275        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder       
276       
277        Wave Q_exp=$(USANSFolder+":DSM:Q_exp")
278        Variable IG,UL,UU
279
280//      WAVE IG_save = root:DSM:IG_save
281        If (ii == jj)
282          UL=0.0
283        Else
284          UL=sqrt(Q_exp[jj]^2-Q_exp[ii]^2)
285        EndIf
286        UU=sqrt(Q_exp[jj+1]^2-Q_exp[ii]^2)
287       
288        //in FORTRAN log = natural log....     
289        IG = UU*Q_exp[jj+1]+Q_exp[ii]^2*ln(UU+Q_exp[jj+1])
290        IG -= UL*Q_exp[jj]
291        IG -= Q_exp[ii]^2*ln(UL+Q_exp[jj])
292        IG *= 0.5
293//      IG_save[ii][jj] = IG
294       
295        Return IG
296End
297
298//
299Function FF(ii,jj)
300        Variable ii,jj
301
302        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
303
304        Variable FF
305        NVAR dqv = $(USANSFolder+":DSM:gDqv")
306
307        FF = (1.0/dqv)*(0.5+HH(ii,jj))
308        Return FF
309End
310
311//
312Function GG(ii,jj)
313        Variable ii,jj
314
315        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
316
317        Variable GG
318        NVAR dqv = $(USANSFolder+":DSM:gDqv")
319       
320        GG = (1.0/dqv)*(0.5-HH(ii,jj))
321        Return  GG
322End
323//
324Function HH(ii,jj)
325        Variable ii,jj
326
327        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
328
329        Wave Q_exp=$(USANSFolder+":DSM:Q_exp")
330        Variable HH
331       
332        HH = 0.5*(Q_exp[jj+1]+Q_exp[jj])/(Q_exp[jj+1]-Q_exp[jj])
333        HH -= (1.0/(Q_exp[jj+1]-Q_exp[jj]))*(CC(ii,jj+1)-CC(ii,jj))
334        return HH
335End
336//
337//
338Function CC(ii,jj)
339        Variable ii,jj
340
341        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
342       
343        wave Q_exp = $(USANSFolder+":DSM:Q_exp")
344        Variable CC
345       
346        If (ii == jj)
347          CC = 0.0
348        Else
349          CC = (Q_exp[jj]-Q_exp[ii])^0.5
350        EndIf
351        Return CC
352End
353
354// QROMO is a gerneric NR routine that takes function arguments
355// Call Qromo(Integrand,lower,dqv,Q_exp(N),m,SS,Midpnt)
356// -- here, it is always called with Integrand and Midpnt as the functions
357// -- so rewrite in a simpler way....
358//
359// SS is the returned value?
360// H_wave, S_wave (original names H,S)
361//
362// modified using c-version in NR (pg 143)
363Function QROMO(A,B,qi,m)
364        Variable A,B,qi,m
365
366        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
367       
368        Variable EPS,JMAX,JMAXP,KM,K
369        EPS=1.E-6
370        JMAX=14
371        KM=4
372        K=KM+1
373       
374        Make/O/D/N=(JMAX) $(USANSFolder+":DSM:S_wave")
375        Make/O/D/N=(JMAX+1) $(USANSFolder+":DSM:H_wave")
376        wave S_wave=$(USANSFolder+":DSM:S_wave")
377        wave H_wave=$(USANSFolder+":DSM:H_wave")
378        S_wave=0
379        H_wave=0
380       
381        H_Wave[0] = 1
382       
383        variable jj,SS,DSS
384       
385        for(jj=0;jj<jmax;jj+=1)
386                S_wave[jj] = Midpnt(A,B,jj,qi,m)                //remove FUNC, always call Integrand from within Midpnt
387                IF (jj>=KM)             //after 1st 5 points calculated
388                    POLINT(H_wave,S_wave,jj-KM,KM,0.0,SS,DSS)           //ss, dss returned
389                    IF (ABS(DSS) < EPS*ABS(SS))
390                        RETURN ss
391                    endif
392                ENDIF
393//        S_wave[jj+1]=S_wave[jj]
394          H_wave[jj+1]=H_wave[jj]/9.
395        endfor
396       
397        DoAlert 0,"Too many steps in QROMO"
398        return 1                        //error if you get here
399END
400
401//
402// see NR pg 109
403// - Given input arrays xa[1..n] and ya[1..n], and a given value x
404// return a value y and an error estimate dy. if P(x) is the polynomial of
405// degree N-1 such that P(xai) = yai, then the returned value y=P(x)
406//
407// arrays XA[] and YA[] are passed in with an offset of the index
408// of where to start the interpolation
409Function POLINT(XA,YA,offset,N,X,Y,DY)
410        Wave XA,YA
411        Variable offset,N,X,&Y,&DY
412       
413        Variable ii,mm,nmax,ns,dif,den,ho,hp,wi,dift
414
415        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
416       
417        NMAX=10
418       
419        Make/O/D/N=(NMAX) $(USANSFolder+":DSM:Ci"),$(USANSFolder+":DSM:Di")
420        wave Ci = $(USANSFolder+":DSM:Ci")
421        wave Di = $(USANSFolder+":DSM:Di")
422
423        NS=1
424        DIF=ABS(X-XA[0])
425        for(ii=0;ii<n;ii+=1)
426                DIFT=ABS(X-XA[ii+offset])
427                IF (DIFT < DIF)
428                        NS=ii
429                        DIF=DIFT
430                ENDIF
431                Ci[ii]=YA[ii+offset]
432                Di[ii]=YA[ii+offset]
433        endfor
434       
435        Y=YA[NS+offset]
436        NS=NS-1
437        for(mm=1;mm<n-1;mm+=1)
438                for(ii=0;ii<(n-mm);ii+=1)
439                        HO=XA[ii+offset]-X
440                        HP=XA[ii+offset+mm]-X
441                        Wi=Ci[ii+1]-Di[ii]
442                        DEN=HO-HP
443                        IF(DEN == 0.)
444                                print "den == 0 in POLINT - ERROR!!!"
445                        endif
446                        DEN=Wi/DEN
447                        Di[ii]=HP*DEN
448                        Ci[ii]=HO*DEN
449                endfor  //ii
450                IF (2*NS < (N-mm) )
451                        DY=Ci[NS+1]
452                ELSE
453                        DY=Di[NS]
454                        NS=NS-1
455                ENDIF
456                Y=Y+DY
457        endfor  //mm
458        RETURN (0)              //y and dy are returned as pass-by-reference
459END
460
461//
462// FUNC is always Integrand()
463// again, see the c-version, NR pg 142
464Function MIDPNT(A,B,N,qi,m)
465        Variable A,B,N,qi,m
466       
467        Variable it,tnm,del,ddel,x,summ,jj
468
469        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
470       
471        NVAR S_ret = $(USANSFolder+":DSM:gS")
472       
473        IF (N == 0)
474                S_ret=(B-A)*Integrand_dsm(0.5*(A+B),qi,m)
475//              Print "N==0, S_ret = ",s_ret
476                return(S_ret)
477                        //IT=1
478        ELSE
479                //AJJ This code is confusing!
480//              it = 1
481//              for(jj=1;jj<n-1;jj+=1)
482//                      it *= 3
483//              endfor
484                //AJJ Equivalent and simpler   
485                it = 3^(N-1)   
486                //
487                TNM=IT
488                DEL=(B-A)/(3.*TNM)
489                DDEL=DEL+DEL
490                X=A+0.5*DEL
491                SUMm=0.
492                for(jj=1;jj<=it;jj+=1)
493                        SUMm=SUMm+Integrand_dsm(X,qi,m)
494                        X=X+DDEL
495                        SUMm=SUMm+Integrand_dsm(X,qi,m)
496                        X=X+DEL
497                endfor
498                S_ret=(S_ret+(B-A)*SUMm/TNM)/3.
499                IT=3*IT
500        ENDIF
501        return S_ret
502END
503
504//////////// end of Lake desmearing routines
505
506// - Almost everything below here is utility routines for data handling, panel
507// controls, and all the fluff that makes this useable. Note that this is
508// a lot more code than the actual guts of the Lake method!
509// (the guts of the iteration are in the DemsearButtonProc)
510
511
512// add three "fake" resolution columns to the output file so that it
513// looks like a regular SANS data set, but make the sigQ column 100x smaller than Q
514// so that there is effectively no resolution smearing. Set Qbar = Q, and fs = 1
515//
516// SRK 06 FEB 06
517//
518Function WriteUSANSDesmeared(fullpath,lo,hi,dialog)
519        String fullpath
520        Variable lo,hi,dialog           //=1 will present dialog for name
521       
522        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder       
523       
524        String termStr="\r\n"
525        String destStr = USANSFolder+":DSM:"
526        String formatStr = "%15.6g %15.6g %15.6g %15.6g %15.6g %15.6g"+termStr
527       
528        Variable refNum,integer,realval
529       
530        //*****these waves MUST EXIST, or IGOR Pro will crash, with a type 2 error****
531        WAVE Q_dsm =$(destStr + "Q_dsm")
532        WAVE I_dsm=$(destStr + "I_dsm")
533        WAVE S_dsm=$(destStr + "S_dsm")
534       
535        //check each wave
536        If(!(WaveExists(Q_dsm)))
537                Abort "Q_dsm DNExist in WriteUSANSDesmeared()"
538        Endif
539        If(!(WaveExists(I_dsm)))
540                Abort "I_dsm DNExist in WriteUSANSDesmeared()"
541        Endif
542        If(!(WaveExists(S_dsm)))
543                Abort "S_dsm DNExist in WriteUSANSDesmeared()"
544        Endif
545       
546        // 06 FEB 06 SRK
547        // make dummy waves to hold the "fake" resolution, and write it as the last 3 columns
548        //
549        Duplicate/O Q_dsm,res1,res2,res3
550        res3 = 1                // "fake" beamstop shadowing
551        res1 /= 100             //make the sigmaQ so small that there is no smearing
552       
553        if(dialog)
554                Open/D refnum as fullpath+".dsm"                //won't actually open the file
555                If(cmpstr(S_filename,"")==0)
556                        //user cancel, don't write out a file
557                        Close/A
558                        Abort "no data file was written"
559                Endif
560                fullpath = S_filename
561        Endif
562       
563        //write out partial set?
564        Duplicate/O Q_dsm,tq,ti,te
565        ti=I_dsm
566        te=S_dsm
567        if( (lo!=hi) && (lo<hi))
568                redimension/N=(hi-lo+1) tq,ti,te,res1,res2,res3         //lo to hi, inclusive
569                tq=Q_dsm[p+lo]
570                ti=I_dsm[p+lo]
571                te=S_dsm[p+lo]
572        endif
573       
574        //tailor the output given the type of data written out...
575        String samStr="",dateStr="",str1,str2
576       
577        NVAR m = $(USANSFolder+":DSM:gPowerM")                          // power law exponent
578        NVAR chiFinal = $(USANSFolder+":DSM:gChi2Final")                //chi^2 final
579        NVAR iter = $(USANSFolder+":DSM:gIterations")           //total number of iterations
580       
581        //get the number of spline passes from the wave note
582        String noteStr
583        Variable boxPass,SplinePass
584        noteStr=note(I_dsm)
585        BoxPass = NumberByKey("BOX", noteStr, "=", ";")
586        splinePass = NumberByKey("SPLINE", noteStr, "=", ";")
587       
588        samStr = fullpath
589        dateStr="CREATED: "+date()+" at  "+time()
590        sprintf str1,"Chi^2 = %g   PowerLaw m = %4.2f   Iterations = %d",chiFinal,m,iter
591        sprintf str2,"%d box smooth passes and %d smoothing spline passes",boxPass,splinePass
592
593       
594        //actually open the file
595        Open refNum as fullpath
596       
597        fprintf refnum,"%s"+termStr,samStr
598        fprintf refnum,"%s"+termStr,str1
599        fprintf refnum,"%s"+termStr,str2
600        fprintf refnum,"%s"+termStr,dateStr
601       
602        wfprintf refnum, formatStr, tq,ti,te,res1,res2,res3
603       
604        Close refnum
605       
606        Killwaves/Z ti,tq,te,res1,res2,res3
607       
608        Return(0)
609End
610
611/// procedures to do the extrapolation to high Q
612// very similar to the procedures in the Invariant package
613//
614//create the wave to extrapolate
615// w is the input q-values
616Function DSM_SetExtrWaves(w)
617        Wave w
618
619        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
620
621        Variable num_extr=25
622       
623        SetDataFolder $(USANSFolder+":DSM")
624       
625        Make/O/D/N=(num_extr) extr_hqq,extr_hqi
626        extr_hqi=1              //default values
627
628        //set the q-range
629        Variable qmax,num
630//      qmax=0.03
631
632        num=numpnts(w)
633        qmax=6*w[num-1]
634       
635        extr_hqq = w[num-1] + x * (qmax-w[num-1])/num_extr
636       
637        SetDataFolder root:
638        return(0)
639End
640
641//creates I_ext,Q_ext,S_ext with extended q-values
642//
643// if num_extr == 0 , the input waves are returned as _ext
644//
645// !! uses simple linear extrapolation at low Q - just need something
646// reasonable in the waves to keep from getting smoothing artifacts
647// - uses power law at high q
648Function ExtendToSmooth(qw,iw,sw,nbeg,nend,num_extr)
649        Wave qw,iw,sw
650        Variable nbeg,nend,num_extr
651
652        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
653       
654        Variable/G V_FitMaxIters=300
655        Variable/G V_fitOptions=4               //suppress the iteration window
656        Variable num_new,qmax,num,qmin
657        num=numpnts(qw)
658       
659        num_new = num + 2*num_extr
660       
661//      Print "num,num_new",num,num_new
662       
663        SetDataFolder $(USANSFolder+":DSM")
664        Make/O/D/N=(num_new) Q_ext,I_ext,S_ext
665       
666        if(num_extr == 0)               //the extended waves are the input, get out
667                Q_ext = qw
668                I_ext = iw
669                S_ext = sw
670                setDatafolder root:
671                return (0)
672        endif
673       
674        //make the extensions
675        Make/O/D/N=(num_extr) hqq,hqi,lqq,lqi
676        hqi=1           //default values
677        lqi=0
678        //set the q-range based on the high/low values of the data set
679//      qmin=1e-6
680        qmin= qw[0]*0.5
681        qmax = qw[num-1]*2
682       
683        hqq = qw[num-1] + x * (qmax-qw[num-1])/num_extr
684        lqq = qmin + x * (qw[0]-qmin)/num_extr
685       
686        //do the fits
687        Duplicate/O iw dummy                    //use this as the destination to suppress fit_ from being appended
688       
689        //Use simple linear fits        line: y = K0+K1*x
690        CurveFit/Q line iw[0,(nbeg-1)] /X=qw /W=sw /D=dummy
691        Wave W_coef=W_coef
692        lqi=W_coef[0]+W_coef[1]*lqq
693//     
694// Guinier or Power-law fits
695//             
696//      Make/O/D G_coef={100,-100}              //input
697//      FuncFit DSM_Guinier_Fit G_coef iw[0,(nbeg-1)] /X=qw /W=sw /D
698//      lqi= DSM_Guinier_Fit(G_coef,lqq)
699       
700//      Printf "I(q=0) = %g (1/cm)\r",G_coef[0]
701//      Printf "Rg = %g (A)\r",sqrt(-3*G_coef[1])
702               
703        Make/O/D P_coef={0,1,-4}                        //input  --- (set background to zero and hold fixed)
704        CurveFit/Q/N/H="100" Power kwCWave=P_coef  iw[(num-1-nend),(num-1)] /X=qw /W=sw /D=dummy
705        hqi=P_coef[0]+P_coef[1]*hqq^P_coef[2]
706       
707//      Printf "Power law exponent = %g\r",P_coef[2]
708//      Printf "Pre-exponential = %g\r",P_coef[1]
709       
710        // concatenate the extensions
711        Q_ext[0,(num_extr-1)] = lqq[p]
712        Q_ext[num_extr,(num_extr+num-1)] = qw[p-num_extr]
713        Q_ext[(num_extr+num),(2*num_extr+num-1)] = hqq[p-num_extr-num]
714        I_ext[0,(num_extr-1)] = lqi[p]
715        I_ext[num_extr,(num_extr+num-1)] = iw[p-num_extr]
716        I_ext[(num_extr+num),(2*num_extr+num-1)] = hqi[p-num_extr-num]
717        S_ext[0,(num_extr-1)] = sw[0]
718        S_ext[num_extr,(num_extr+num-1)] = sw[p-num_extr]
719        S_ext[(num_extr+num),(2*num_extr+num-1)] = sw[num-1]
720       
721        killwaves/z dummy
722        SetDataFolder root:
723        return(0)
724End
725
726// pass in the (smeared) experimental data and find the power-law extrapolation
727// 10 points is usually good enough, unless the data is crummy
728// returns the prediction for the exponent
729//
730Function DSM_DoExtrapolate(qw,iw,sw,nend)
731        Wave qw,iw,sw
732        Variable nend
733
734        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
735       
736        Setdatafolder $(USANSFolder+":DSM")
737       
738//      Wave extr_lqi=extr_lqi
739//      Wave extr_lqq=extr_lqq
740        Wave extr_hqi=extr_hqi
741        Wave extr_hqq=extr_hqq
742        Variable/G V_FitMaxIters=300
743        Variable/G V_fitOptions=4               //suppress the iteration window
744        Variable num=numpnts(iw),retVal
745       
746        Make/O/D P_coef={0,1,-4}                        //input
747//      Make/O/T Constr={"K2<0","K2 > -20"}
748        //(set background to zero and hold fixed)
749        CurveFit/H="100" Power kwCWave=P_coef  iw[(num-1-nend),(num-1)] /X=qw /W=sw /D
750        extr_hqi=P_coef[0]+P_coef[1]*extr_hqq^P_coef[2]
751       
752        // for the case of data with a background
753//      Make/O/D P_coef={0,1,-4}                        //input
754//      //(set background to iw[num-1], let it be a free parameter
755//      P_coef[0] = iw[num-1]
756//      CurveFit Power kwCWave=P_coef  iw[(num-1-nend),(num-1)] /X=qw /W=sw /D
757//      extr_hqi=P_coef[0]+P_coef[1]*extr_hqq^P_coef[2]
758       
759       
760        Printf "Smeared Power law exponent = %g\r",P_coef[2]
761        Printf "**** For Desmearing, use a Power law exponent of %5.1f\r",P_coef[2]-1
762       
763        retVal = P_coef[2]-1
764        SetDataFolder root:
765        return(retVal)
766End
767
768Function DSM_Guinier_Fit(w,x) //: FitFunc
769        Wave w
770        Variable x
771       
772        //fit data to I(q) = A*exp(B*q^2)
773        // (B will be negative)
774        //two parameters
775        Variable a,b,ans
776        a=w[0]
777        b=w[1]
778        ans = a*exp(b*x*x)
779        return(ans)
780End
781
782Proc Desmear_Graph()
783        String USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
784
785        PauseUpdate; Silent 1           // building window...
786        Display /W=(5,44,408,558) /K=1
787        ModifyGraph cbRGB=(51664,44236,58982)
788        DoWindow/C Desmear_Graph
789        ControlBar 160
790        // break into tabs
791        TabControl DSM_Tab,pos={5,3},size={392,128},proc=DSM_TabProc
792        TabControl DSM_Tab,labelBack=(49151,49152,65535),tabLabel(0)="Load"
793        TabControl DSM_Tab,tabLabel(1)="Mask",tabLabel(2)="Extrapolate"
794        TabControl DSM_Tab,tabLabel(3)="Smooth",tabLabel(4)="Desmear",value= 0
795       
796        //always visible - revert and save
797        //maybe the wrong place here?
798        Button DSMControlA,pos={225,135},size={80,20},proc=DSM_RevertButtonProc,title="Revert"
799        Button DSMControlA,help={"Revert the smeared data to its original state and start over"}
800        Button DSMControlB,pos={325,135},size={50,20},proc=DSM_SaveButtonProc,title="Save"
801        Button DSMControlB,help={"Save the desmeared data set"}
802        Button DSMControlC,pos={25,135},size={50,20},proc=DSM_HelpButtonProc,title="Help"
803        Button DSMControlC,help={"Show the help file for desmearing"}
804       
805        // add the controls to each tab ---- all names start with "DSMControl_"
806
807        //tab(0) Load - initially visible
808        Button DSMControl_0a,pos={23,39},size={80,20},proc=DSM_LoadButtonProc,title="Load Data"
809        Button DSMControl_0a,help={"Load slit-smeared USANS data = \".cor\" files"}
810        CheckBox DSMControl_0b,pos={26,74},size={80,14},proc=DSM_LoadCheckProc,title="Log Axes?"
811        CheckBox DSMControl_0b,help={"Toggle Log/Lin Q display"},value= 1
812        TitleBox DSMControl_0c,pos={120,37},size={104,19},font="Courier",fSize=10
813        TitleBox DSMControl_0c,variable= $(USANSFolder+":DSM:gStr1")
814        //second message string not used currently
815//      TitleBox DSMControl_0d,pos={120,57},size={104,19},font="Courier",fSize=10
816//      TitleBox DSMControl_0d,variable= root:DSM:gStr2
817       
818        //tab(1) Mask
819        Button DSMControl_1a,pos={20,35},size={90,20},proc=DSM_MyMaskProc,title="Mask Point"            //bMask
820        Button DSMControl_1a,help={"Toggles the masking of the selected data point"}
821        Button DSMControl_1a,disable=1
822        Button DSMControl_1b,pos={20,65},size={140,20},proc=DSM_MaskGTCursor,title="Mask Q >= Cursor"           //bMask
823        Button DSMControl_1b,help={"Toggles the masking of all q-values GREATER than the current cursor location"}
824        Button DSMControl_1b,disable=1
825        Button DSMControl_1c,pos={20,95},size={140,20},proc=DSM_MaskLTCursor,title="Mask Q <= Cursor"           //bMask
826        Button DSMControl_1c,help={"Toggles the masking of all q-values LESS than the current cursor location"}
827        Button DSMControl_1c,disable=1
828        Button DSMControl_1d,pos={180,35},size={90,20},proc=DSM_ClearMaskProc,title="Clear Mask"                //bMask
829        Button DSMControl_1d,help={"Clears all mask points"}
830        Button DSMControl_1d,disable=1
831//      Button DSMControl_1b,pos={144,66},size={110,20},proc=DSM_MaskDoneButton,title="Done Masking"
832//      Button DSMControl_1b,disable=1
833       
834        //tab(2) Extrapolate
835        Button DSMControl_2a,pos={31,42},size={90,20},proc=DSM_ExtrapolateButtonProc,title="Extrapolate"
836        Button DSMControl_2a,help={"Extrapolate the high-q region with a power-law"}
837        Button DSMControl_2a,disable=1
838        SetVariable DSMControl_2b,pos={31,70},size={100,15},title="# of points"
839        SetVariable DSMControl_2b,help={"Set the number of points for the power-law extrapolation"}
840        SetVariable DSMControl_2b,limits={5,100,1},value=  $(USANSFolder+":DSM:gNptsExtrap")
841        SetVariable DSMControl_2b,disable=1
842        CheckBox DSMControl_2c,pos={157,45},size={105,14},proc=DSM_ExtrapolationCheckProc,title="Show Extrapolation"
843        CheckBox DSMControl_2c,help={"Show or hide the high q extrapolation"},value= 1
844        CheckBox DSMControl_2c,disable=1
845        SetVariable DSMControl_2d,pos={31,96},size={150,15},title="Power Law Exponent"
846        SetVariable DSMControl_2d,help={"Power Law exponent from the fit = the DESMEARED slope - override as needed"}
847        SetVariable DSMControl_2d format="%5.2f"
848        SetVariable DSMControl_2d,limits={-inf,inf,0},value= $(USANSFolder+":DSM:gPowerM")
849        SetVariable DSMControl_2d,disable=1
850       
851        //tab(3) Smooth
852        Button DSMControl_3a,pos={34,97},size={70,20},proc=DSM_SmoothButtonProc,title="Smooth"
853        Button DSMControl_3a,disable=1
854                //BoxCheck
855        CheckBox DSMControl_3b,pos={34,39},size={35,14},title="Box",value= 1
856        CheckBox DSMControl_3b,help={"Use a single pass of 3-point box smoothing"}
857        CheckBox DSMControl_3b,disable=1
858                //SSCheck
859        CheckBox DSMControl_3c,pos={34,60},size={45,14},title="Spline",value= 0
860        CheckBox DSMControl_3c,help={"Use a single pass of a smoothing spline"}
861        CheckBox DSMControl_3c,disable=1
862                //extendCheck
863        CheckBox DSMControl_3d,pos={268,60},size={71,14},title="Extend Data"
864        CheckBox DSMControl_3d,help={"extends the data at both low q and high q to avoid end effects in smoothing"}
865        CheckBox DSMControl_3d,value= 0
866        CheckBox DSMControl_3d,disable=1
867        Button DSMControl_3e,pos={125,97},size={90,20},proc=DSM_SmoothUndoButtonProc,title="Start Over"
868        Button DSMControl_3e,help={"Start the smoothing over again without needing to re-mask the data set"}
869        Button DSMControl_3e,disable=1
870        SetVariable DSMControl_3f,pos={94,60},size={150,15},title="Smoothing factor"
871        SetVariable DSMControl_3f,help={"Smoothing factor for the smoothing spline"}
872        SetVariable DSMControl_3f format="%5.4f"
873        SetVariable DSMControl_3f,limits={0.01,2,0.01},value= $(USANSFolder+":DSM:gSmoothFac")
874        SetVariable DSMControl_3f,disable=1
875        CheckBox DSMControl_3g,pos={268,39},size={90,14},title="Log-scale smoothing?"
876        CheckBox DSMControl_3g,help={"Use log-scaled intensity during smoothing (reverts to linear if negative intensity points found)"}
877        CheckBox DSMControl_3g,value=0
878        CheckBox DSMControl_3g,disable=1
879        ValDisplay DSMControl_3h pos={235,97},title="Chi^2",size={80,20},value=root:Packages:NIST:USANS:DSM:gChi2Smooth
880        ValDisplay DSMControl_3h,help={"This is the Chi^2 value for the smoothed data vs experimental data"}
881        ValDisplay DSMControl_3h,disable=1
882       
883        //tab(4) Desmear
884        Button DSMControl_4a,pos={35,93},size={80,20},proc=DSM_DesmearButtonProc,title="Desmear"
885        Button DSMControl_4a,help={"Do the desmearing - the result is in I_dsm"}
886        Button DSMControl_4a,disable=1
887        SetVariable DSMControl_4b,pos={35,63},size={120,15},title="Chi^2 target"
888        SetVariable DSMControl_4b,help={"Set the targetchi^2 for convergence (recommend chi^2=1)"}
889        SetVariable DSMControl_4b,limits={0,inf,0.1},value= $(USANSFolder+":DSM:gChi2Target")
890        SetVariable DSMControl_4b,disable=1
891        SetVariable DSMControl_4c,pos={35,35},size={80,15},title="dQv"
892        SetVariable DSMControl_4c,help={"Slit height as read in from the data file. 0.117 is the NIST value, override if necessary"}
893        SetVariable DSMControl_4c,limits={-inf,inf,0},value= $(USANSFolder+":DSM:gDqv")
894        SetVariable DSMControl_4c,disable=1
895        TitleBox DSMControl_4d,pos={160,37},size={104,19},font="Courier",fSize=10
896        TitleBox DSMControl_4d,variable= $(USANSFolder+":DSM:gIterStr")
897        TitleBox DSMControl_4d,disable=1
898       
899       
900        SetDataFolder root:
901EndMacro
902
903// function to control the drawing of buttons in the TabControl on the main panel
904// Naming scheme for the buttons MUST be strictly adhered to... else buttons will
905// appear in odd places...
906// all buttons are named DSMControl_NA where N is the tab number and A is the letter denoting
907// the button's position on that particular tab.
908// in this way, buttons will always be drawn correctly :-)
909//
910Function DSM_TabProc(ctrlName,tab) //: TabControl
911        String ctrlName
912        Variable tab
913
914        String ctrlList = ControlNameList("",";"),item="",nameStr=""
915        Variable num = ItemsinList(ctrlList,";"),ii,onTab
916        for(ii=0;ii<num;ii+=1)
917                //items all start w/"DSMControl_"               //11 characters
918                item=StringFromList(ii, ctrlList ,";")
919                nameStr=item[0,10]
920                if(cmpstr(nameStr,"DSMControl_")==0)
921                        onTab = str2num(item[11])                       //12th is a number
922                        ControlInfo $item
923                        switch(abs(V_flag))     
924                                case 1:
925                                        Button $item,disable=(tab!=onTab)
926                                        break
927                                case 2:
928                                        CheckBox $item,disable=(tab!=onTab)
929                                        break
930                                case 5:
931                                        SetVariable $item,disable=(tab!=onTab)
932                                        break
933                                case 10:       
934                                        TitleBox $item,disable=(tab!=onTab)
935                                        break
936                                case 4:
937                                        ValDisplay $item,disable=(tab!=onTab)
938                                        break
939                                // add more items to the switch if different control types are used
940                        endswitch
941                       
942                endif
943        endfor
944       
945        if(tab==1)
946                DSM_MyMaskProc("")              //start maksing if you click on the tab
947        else
948                DSM_MaskDoneButton("")          //masking is done if you click off the tab
949        endif
950       
951        return 0
952End
953
954Proc AppendSmeared()
955        String USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
956
957        SetDataFolder $(USANSFolder+":DSM")
958//      if( strsearch(TraceNameList("Desmear_Graph", "", 1),"I_exp_orig",0,2) == -1)            //Igor 5
959        if( strsearch(TraceNameList("Desmear_Graph", "", 1),"I_exp_orig",0) == -1)
960                AppendToGraph/W=Desmear_Graph  I_exp_orig vs Q_exp_orig
961                ModifyGraph mode=4,marker=19            //3 is markers, 4 is markers and lines
962                ModifyGraph rgb(I_exp_orig)=(0,0,0)
963                ModifyGraph msize=2,grid=1,log=1,mirror=2,standoff=0,tickunit=1
964                ErrorBars/T=0 I_exp_orig Y,wave=(S_exp_orig,S_exp_orig)
965                Legend/N=text0/J "\\F'Courier'\\s(I_exp_orig) I_exp_orig"
966                Label left "Intensity"
967                Label bottom "Q (1/A)"
968        endif
969        //always update the textbox - kill the old one first
970        TextBox/K/N=text1
971//      TextBox/C/N=text1/F=0/A=MT/E=2/X=5.50/Y=0.00 root:DSM:gCurFile                  //Igor 5
972        TextBox/C/N=text1/F=0/A=MT/E=1/X=5.50/Y=0.00 $(USANSFolder+":DSM:gCurFile")
973End
974
975Proc AppendMask()
976        String USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
977
978//      if( strsearch(TraceNameList("Desmear_Graph", "", 1),"MaskData",0,2) == -1)                      //Igor 5
979        if( strsearch(TraceNameList("Desmear_Graph", "", 1),"MaskData",0) == -1)
980                SetDataFolder $(USANSFolder+":DSM:")
981                AppendToGraph/W=Desmear_Graph MaskData vs Q_exp_orig
982                ModifyGraph mode(MaskData)=3,marker(MaskData)=8,msize(MaskData)=2.5,opaque(MaskData)=1
983                ModifyGraph rgb(MaskData)=(65535,16385,16385)
984                setdatafolder root:
985        endif
986end
987
988Proc AppendSmoothed()
989        String USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
990
991//      if( strsearch(TraceNameList("Desmear_Graph", "", 1),"I_smth",0,2) == -1)                        //Igor 5
992        if( strsearch(TraceNameList("Desmear_Graph", "", 1),"I_smth",0) == -1)
993                SetDataFolder $(USANSFolder+":DSM:")
994                AppendToGraph/W=Desmear_Graph I_smth vs Q_smth
995                ModifyGraph/W=Desmear_Graph rgb(I_smth)=(3,52428,1),lsize(I_smth)=2
996                setdatafolder root:
997        endif
998end
999
1000Function RemoveSmoothed()
1001        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
1002
1003        SetDataFolder $(USANSFolder+":DSM:")
1004        RemoveFromGraph/W=Desmear_Graph/Z I_smth
1005        setdatafolder root:
1006end
1007
1008Function RemoveMask()
1009        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
1010
1011        SetDataFolder $(USANSFolder+":DSM:")
1012        RemoveFromGraph/W=Desmear_Graph/Z MaskData
1013        setdatafolder root:
1014end
1015
1016Proc AppendDesmeared()
1017        String USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
1018
1019//      if( strsearch(TraceNameList("Desmear_Graph", "", 1),"I_dsm",0,2) == -1)         //Igor 5
1020        if( strsearch(TraceNameList("Desmear_Graph", "", 1),"I_dsm",0) == -1)
1021                SetDataFolder $(USANSFolder+":DSM:")
1022                AppendToGraph/W=Desmear_Graph I_dsm vs Q_dsm
1023                ModifyGraph mode(I_dsm)=3,marker(I_dsm)=19
1024                ModifyGraph rgb(I_dsm)=(1,16019,65535),msize(I_dsm)=2
1025                ErrorBars/T=0 I_dsm Y,wave=(S_dsm,S_dsm)
1026                setdatafolder root:
1027        endif
1028end
1029
1030Function RemoveDesmeared()
1031        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
1032
1033        SetDataFolder $(USANSFolder+":DSM:")
1034        RemoveFromGraph/W=Desmear_Graph/Z I_dsm
1035        setdatafolder root:
1036end
1037
1038Function AppendExtrapolation()
1039        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
1040
1041//      if( strsearch(TraceNameList("Desmear_Graph", "", 1),"extr_hqi",0,2) == -1)              //Igor 5
1042        if( strsearch(TraceNameList("Desmear_Graph", "", 1),"extr_hqi",0) == -1)
1043                SetDataFolder $(USANSFolder+":DSM:")
1044                AppendToGraph/W=Desmear_Graph extr_hqi vs extr_hqq
1045                ModifyGraph/W=Desmear_Graph lSize(extr_hqi)=2
1046                setdatafolder root:
1047        endif
1048end
1049
1050Function RemoveExtrapolation()
1051        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
1052
1053        SetDataFolder $(USANSFolder+":DSM:")
1054        RemoveFromGraph/W=Desmear_Graph/Z extr_hqi
1055        setdatafolder root:
1056end
1057
1058// step (1) - read in the data, and plot it
1059// clear out all of the "old" waves, remove them from the graph first
1060// reads in a fresh copy of the data
1061//
1062// produces Q_exp, I_exp, S_exp waves (and originals "_orig")
1063// add a dummy wave note that can be changed on later steps
1064//
1065Function DSM_LoadButtonProc(ctrlName) : ButtonControl
1066        String ctrlName
1067
1068        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
1069
1070        String qStr,iStr,sStr,sqStr
1071        Variable nq,dqv,numBad,val
1072       
1073        // remove any of the old traces on the graph and delete the waves
1074        CleanUpJunk()
1075       
1076        SetDataFolder root:
1077        Execute "A_LoadOneDDataWithName(\"\",0)"
1078        //define the waves that the smoothing will be looking for...
1079        SVAR fname = $("root:Packages:NIST:gLastFileName")              //this changes as any data is loaded
1080        SVAR curFile = $(USANSFolder+":DSM:gCurFile")                                   //keep this for title, save
1081        curFile = fname
1082       
1083        qStr = CleanupName((fName + "_q"),0)            //the q-wave
1084        iStr = CleanupName((fName + "_i"),0)            //the i-wave
1085        sStr = CleanupName((fName + "_s"),0)            //the s-wave
1086        sqStr = CleanupName((fName + "sq"),0)           //the sq-wave, which should have -dQv as the elements
1087
1088        String DFStr= CleanupName(fname,0)
1089       
1090        Duplicate/O $("root:"+DFStr+":"+qStr) $(USANSFolder+":DSM:Q_exp ")             
1091        Duplicate/O $("root:"+DFStr+":"+iStr) $(USANSFolder+":DSM:I_exp")               
1092        Duplicate/O $("root:"+DFStr+":"+sStr) $(USANSFolder+":DSM:S_exp ")     
1093        wave Q_exp = $(USANSFolder+":DSM:Q_exp")
1094        Wave I_exp = $(USANSFolder+":DSM:I_exp")
1095        Wave S_exp = $(USANSFolder+":DSM:S_exp")
1096       
1097        // remove any negative q-values (and q=0 values!)(and report this)
1098        // ? and trim the low q to be >= 3.0e-5 (1/A), below this USANS is not reliable.
1099        NumBad = RemoveBadQPoints(Q_exp,I_exp,S_exp,0)
1100        SVAR str1 = $(USANSFolder+":DSM:gStr1")
1101        sprintf str1,"%d negative q-values were removed",numBad
1102       
1103// don't trim off any positive q-values
1104//      val = 3e-5              //lowest "good" q-value from USANS
1105//      NumBad = RemoveBadQPoints(Q_exp,I_exp,S_exp,val-1e-8)
1106//      SVAR str2 = root:DSM:gStr2
1107//      sprintf str2,"%d q-values below q = %g were removed",numBad,val
1108       
1109        Duplicate/O $(USANSFolder+":DSM:Q_exp") $(USANSFolder+":DSM:Q_exp_orig")
1110        Duplicate/O $(USANSFolder+":DSM:I_exp") $(USANSFolder+":DSM:I_exp_orig")
1111        Duplicate/O $(USANSFolder+":DSM:S_exp") $(USANSFolder+":DSM:S_exp_orig")
1112        wave I_exp_orig = $(USANSFolder+":DSM:I_exp_orig")
1113       
1114        nq = numpnts($(USANSFolder+":DSM:Q_exp"))
1115       
1116        dQv = NumVarOrDefault("root:"+DFStr+":USANS_dQv", 0.117 )
1117//      if(WaveExists(sigQ))                    //try to read dQv
1118////            dqv = -sigQ[0][0]
1119////            DoAlert 0,"Found dQv value of " + num2str(dqv)
1120//      else
1121//              dqv = 0.117
1122//      //      dqv = 0.037             //old value
1123//              DoAlert 0,"Could not find dQv in the data file - using " + num2str(dqv)
1124//      endif
1125        NVAR gDqv = $(USANSFolder+":DSM:gDqv")                          //needs to be global for Weights_L()
1126        NVAR gNq = $(USANSFolder+":DSM:gNq")
1127        //reset the globals
1128        gDqv = dqv
1129        gNq = nq
1130       
1131        // append the (blank) wave note to the intensity wave
1132        Note I_exp,"BOX=0;SPLINE=0;"
1133        Note I_exp_orig,"BOX=0;SPLINE=0;"
1134       
1135        //draw the graph
1136        Execute "AppendSmeared()"
1137       
1138        SetDataFolder root:
1139End
1140
1141// remove any q-values <= val
1142Function RemoveBadQPoints(qw,iw,sw,val)
1143        Wave qw,iw,sw
1144        Variable val
1145       
1146        Variable ii,num,numBad,qval
1147        num = numpnts(qw)
1148       
1149        ii=0
1150        numBad=0
1151        do
1152                qval = qw[ii]
1153                if(qval <= val)
1154                        numBad += 1
1155                else            //keep the points
1156                        qw[ii-numBad] = qval
1157                        iw[ii-numBad] = iw[ii]
1158                        sw[ii-numBad] = sw[ii]
1159                endif
1160                ii += 1
1161        while(ii<num)
1162        //trim the end of the waves
1163        DeletePoints num-numBad, numBad, qw,iw,sw
1164        return(numBad)
1165end
1166
1167// if mw = Nan, keep the point, if a numerical value, delete it
1168Function RemoveMaskedPoints(mw,qw,iw,sw)
1169        Wave mw,qw,iw,sw
1170       
1171        Variable ii,num,numBad,mask
1172        num = numpnts(qw)
1173       
1174        ii=0
1175        numBad=0
1176        do
1177                mask = mw[ii]
1178                if(numtype(mask) != 2)          //if not NaN
1179                        numBad += 1
1180                else            //keep the points that are NaN
1181                        qw[ii-numBad] = qw[ii]
1182                        iw[ii-numBad] = iw[ii]
1183                        sw[ii-numBad] = sw[ii]
1184                endif
1185                ii += 1
1186        while(ii<num)
1187        //trim the end of the waves
1188        DeletePoints num-numBad, numBad, qw,iw,sw
1189        return(numBad)
1190end
1191
1192// produces the _msk waves that have the new number of data points
1193//
1194Function DSM_MaskDoneButton(ctrlName) : ButtonControl
1195        String ctrlName
1196
1197        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
1198
1199//      Variable aExists= strlen(CsrInfo(A)) > 0                        //Igor 5
1200        Variable aExists= strlen(CsrWave(A)) > 0                        //Igor 4
1201        if(!aExists)
1202                return(1)               //possibly reverted data, no cursor, no Mask wave
1203        endif
1204       
1205        Duplicate/O $(USANSFolder+":DSM:Q_exp_orig"),$(USANSFolder+":DSM:Q_msk")
1206        Duplicate/O $(USANSFolder+":DSM:I_exp_orig"),$(USANSFolder+":DSM:I_msk")
1207        Duplicate/O $(USANSFolder+":DSM:S_exp_orig"),$(USANSFolder+":DSM:S_msk")
1208        Wave Q_msk=$(USANSFolder+":DSM:Q_msk")
1209        Wave I_msk=$(USANSFolder+":DSM:I_msk")
1210        Wave S_msk=$(USANSFolder+":DSM:S_msk")
1211       
1212        //finish up - trim the data sets and reassign the working set
1213        Wave MaskData=$(USANSFolder+":DSM:MaskData")
1214       
1215        RemoveMaskedPoints(MaskData,Q_msk,I_msk,S_msk)
1216
1217        //reset the number of points
1218        NVAR gNq = $(USANSFolder+":DSM:gNq")
1219        gNq = numpnts(Q_msk)
1220       
1221        Cursor/K A
1222        HideInfo
1223       
1224        return(0)
1225End
1226
1227
1228// not quite the same as revert
1229Function DSM_ClearMaskProc(ctrlName) : ButtonControl
1230        String ctrlName
1231       
1232        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
1233       
1234        Wave MaskData=$(USANSFolder+":DSM:MaskData")
1235        MaskData = NaN
1236       
1237        return(0)
1238end
1239
1240// when the mask button is pressed, A must be on the graph
1241// Displays MaskData wave on the graph
1242//
1243Function DSM_MyMaskProc(ctrlName) : ButtonControl
1244        String ctrlName
1245       
1246        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder
1247       
1248        Wave data=$(USANSFolder+":DSM:I_exp_orig")
1249       
1250//      Variable aExists= strlen(CsrInfo(A)) > 0                        //Igor 5
1251        Variable aExists= strlen(CsrWave(A)) > 0                        //Igor 4
1252       
1253// need to get rid of old smoothed data if data is re-masked
1254        Execute "RemoveSmoothed()"
1255        SetDataFolder $(USANSFolder+":DSM")
1256        Killwaves/Z I_smth,Q_smth,S_smth
1257               
1258        if(aExists)             //mask the selected point
1259                // toggle NaN (keep) or Data value (= masked)
1260                Wave MaskData
1261                MaskData[pcsr(A)] = (numType(MaskData[pcsr(A)])==0) ? NaN : data[pcsr(A)]               //if NaN, doesn't plot
1262        else
1263                Cursor /A=1/H=1/L=1/P/W=Desmear_Graph A I_exp_orig leftx(I_exp_orig)
1264                ShowInfo
1265                //if the mask wave does not exist, make one
1266                if(exists("MaskData") != 1)
1267                        Duplicate/O Q_exp_orig MaskData
1268                        MaskData = NaN          //use all data
1269                endif
1270                Execute "AppendMask()" 
1271        endif
1272
1273        SetDataFolder root:
1274
1275        return(0)
1276End
1277
1278// when the mask button is pressed, A must be on the graph
1279// Displays MaskData wave on the graph
1280//
1281Function DSM_MaskLTCursor(ctrlName) : ButtonControl
1282        String ctrlName
1283
1284        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder       
1285               
1286//      Variable aExists= strlen(CsrInfo(A)) > 0                        //Igor 5
1287        Variable aExists= strlen(CsrWave(A)) > 0                        //Igor 4
1288       
1289        if(!aExists)
1290                return(1)
1291        endif
1292// need to get rid of old smoothed data if data is re-masked
1293        Execute "RemoveSmoothed()"
1294        SetDataFolder $(USANSFolder+":DSM")
1295        Killwaves/Z I_smth,Q_smth,S_smth
1296
1297        Wave data=I_exp_orig
1298
1299        Variable pt,ii
1300        pt = pcsr(A)
1301        for(ii=pt;ii>=0;ii-=1)
1302                // toggle NaN (keep) or Data value (= masked)
1303                Wave MaskData
1304                MaskData[ii] = (numType(MaskData[ii])==0) ? NaN : data[ii]              //if NaN, doesn't plot
1305        endfor
1306
1307        SetDataFolder root:
1308        return(0)
1309End
1310
1311// when the mask button is pressed, A must be on the graph
1312// Displays MaskData wave on the graph
1313//
1314Function DSM_MaskGTCursor(ctrlName) : ButtonControl
1315        String ctrlName
1316       
1317        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder       
1318
1319       
1320//      Variable aExists= strlen(CsrInfo(A)) > 0                        //Igor 5
1321        Variable aExists= strlen(CsrWave(A)) > 0                        //Igor 4
1322       
1323        if(!aExists)
1324                return(1)
1325        endif
1326// need to get rid of old smoothed data if data is re-masked
1327        Execute "RemoveSmoothed()"
1328        SetDataFolder $(USANSFolder+":DSM")
1329        Killwaves/Z I_smth,Q_smth,S_smth
1330
1331        Wave data=I_exp_orig
1332
1333        Variable pt,ii,endPt
1334        endPt=numpnts(MaskData)
1335        pt = pcsr(A)
1336        for(ii=pt;ii<endPt;ii+=1)
1337                // toggle NaN (keep) or Data value (= masked)
1338                Wave MaskData
1339                MaskData[ii] = (numType(MaskData[ii])==0) ? NaN : data[ii]              //if NaN, doesn't plot
1340        endfor
1341
1342        SetDataFolder root:
1343
1344        return(0)
1345End
1346
1347Function CleanUpJunk()
1348        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder       
1349
1350        // clean up the old junk on the graph, /Z for no error
1351        Execute "RemoveExtrapolation()"
1352        Execute "RemoveDesmeared()"
1353        Execute "RemoveSmoothed()"
1354        Execute "RemoveMask()"
1355       
1356        //remove the cursor
1357        Cursor/K A
1358       
1359        //always initialize these
1360        String/G $(USANSFolder+":DSM:gStr1") = ""
1361        String/G $(USANSFolder+":DSM:gStr2") = ""
1362        String/G $(USANSFolder+":DSM:gIterStr") = ""
1363       
1364        // clean up the old waves from smoothing and desmearing steps
1365        SetDataFolder $(USANSFolder+":DSM")
1366        Killwaves/Z I_smth,I_dsm,I_dsm_sm,Q_smth,Q_dsm,S_smth,S_dsm,Yi_SS,Yq_SS
1367        Killwaves/Z Weights,FW,R_wave,S_wave,H_wave,Di,Ci
1368        Killwaves/Z Is_old,I_old,err
1369        Killwaves/Z Q_ext,I_ext,S_ext,hqq,hqi,lqq,lqi
1370        Killwaves/Z MaskData,Q_msk,I_msk,S_msk
1371        Killwaves/Z Q_work,I_work,S_work                                //working waves for desmearing step
1372        SetDataFolder root:
1373End
1374
1375// does not alter the data sets - reports a power law
1376// exponent and makes it global so it will automatically
1377// be used during the desmearing
1378//
1379// generates extr_hqi vs extr_hqq that are Appended to the graph
1380Function DSM_ExtrapolateButtonProc(ctrlName) : ButtonControl
1381        String ctrlName
1382
1383        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder       
1384
1385        NVAR nend = $(USANSFolder+":DSM:gNptsExtrap")
1386        NVAR m_pred = $(USANSFolder+":DSM:gPowerM")
1387       
1388        SetDataFolder $(USANSFolder+":DSM")
1389//use masked data if it exists
1390        if(exists("I_msk")==1 && exists("Q_msk")==1 && exists("S_msk")==1)
1391                wave Qw = $(USANSFolder+":DSM:Q_msk")
1392                Wave Iw = $(USANSFolder+":DSM:I_msk")
1393                Wave Sw = $(USANSFolder+":DSM:S_msk")
1394        else
1395                //start from the "_exp" waves
1396                if(exists("I_exp")==1 && exists("Q_exp")==1 && exists("S_exp")==1)
1397                        wave Qw = $(USANSFolder+":DSM:Q_exp")
1398                        Wave Iw = $(USANSFolder+":DSM:I_exp")
1399                        Wave Sw = $(USANSFolder+":DSM:S_exp")
1400                endif
1401        endif
1402        SetDataFolder root:
1403       
1404        DSM_SetExtrWaves(Qw)
1405        m_pred = DSM_DoExtrapolate(Qw,Iw,Sw,nend)
1406        AppendExtrapolation()
1407       
1408        return(0)
1409End
1410
1411//smooths the data in steps as requested...
1412//
1413// typically do a simple Box smooth first,
1414// then do a smoothing spline, keeping the same number of data points
1415//
1416// chi-squared is reported - so you can see how "bad" the smoothing is
1417// smoothing of the data is done on a log(I) scale if requested
1418// setting doLog variable to 0 will return to linear smoothing
1419// (I see little difference)
1420//
1421// start from the "_smth" waves if they exist
1422// otheriwse start from the working waves
1423//
1424// create Q_smth, I_smth, S_smth
1425// keep track of the smoothing types and passes in the wave note
1426//
1427Function DSM_SmoothButtonProc(ctrlName) : ButtonControl
1428        String ctrlName
1429
1430        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder       
1431
1432        SetDataFolder $(USANSFolder+":DSM")     
1433
1434        Variable ii,new_n,pass,nq_ext,offset,doLog=1
1435        String noteStr=""
1436       
1437        // want log scaling of intensity during smoothing?
1438        ControlInfo DSMControl_3g
1439        doLog = V_value
1440                       
1441////    if(exists("I_smth")==1 && exists("Q_smth")==1 && exists("S_smth")==1 && ! freshMask)
1442        if(exists("I_smth")==1 && exists("Q_smth")==1 && exists("S_smth")==1)
1443                //start from the smoothed waves --- just need the wave references
1444        else
1445                //start from the "msk", creating smth waves
1446                if(exists("I_msk")==1 && exists("Q_msk")==1 && exists("S_msk")==1)
1447                        wave Q_msk,I_msk,S_msk
1448                        Duplicate/O I_msk,I_smth,Q_smth,S_smth
1449                        I_smth = I_msk
1450                        Q_smth = Q_msk
1451                        S_smth = S_msk
1452                else
1453                        //start from the "_exp" waves
1454                        if(exists("I_exp")==1 && exists("Q_exp")==1 && exists("S_exp")==1)
1455                                wave Q_exp,I_exp,S_exp
1456                                Duplicate/O I_exp,I_smth,Q_smth,S_smth
1457                                I_smth = I_exp
1458                                Q_smth = Q_exp
1459                                S_smth = S_exp
1460                        endif
1461                endif
1462        endif
1463       
1464        wave Q_smth,I_smth,S_smth
1465
1466        // extend the data to avoid end effects
1467        //creates I_ext,Q_ext,S_ext with extended q-values
1468        // fit 15 pts at each end, typically add 10 pts to each end
1469        // does nothing if num_extr = 0
1470        ControlInfo/W=Desmear_Graph DSMControl_3d               //extendCheck
1471        if(V_value == 1)
1472                ExtendToSmooth(Q_smth,I_smth,S_smth,15,15,10)
1473        else
1474                ExtendToSmooth(Q_smth,I_smth,S_smth,15,15,0)            //don't extend, just use the original data
1475        endif
1476       
1477        //whether extending or not, the working data is "_ext", set by ExtendToSmooth()
1478        SetDataFolder $(USANSFolder+":DSM")     
1479        wave Q_ext,I_ext ,S_ext
1480       
1481        noteStr=note(I_smth)
1482        Note I_ext , noteStr
1483       
1484        WaveStats/Q I_ext
1485        if(V_min<=0)
1486                Print "negative itensity found, using linear scale for smoothing"
1487                doLog = 0
1488        endif
1489       
1490        if(doLog)
1491                //convert to log scale
1492                Duplicate/O I_ext I_log,I_log_err
1493                Wave I_log ,I_log_err
1494                I_log = log(I_ext)
1495                WaveStats/Q I_log
1496                offset = 2*(-V_min)             
1497                I_log += offset
1498                I_log_err = S_ext/(2.30*I_ext)
1499                I_ext = I_log
1500        endif   
1501        //
1502       
1503        ControlInfo/W=Desmear_Graph DSMControl_3b               //BoxCheck
1504        if(V_value == 1)
1505                //do a simple Box smooth first - number of points does not change
1506                // fills ends with neighboring value (E=3) (n=3 points in smoothing window)     
1507                Smooth/E=3/B 3, I_ext
1508               
1509                noteStr=note(I_ext)
1510                pass = NumberByKey("BOX", noteStr, "=", ";")
1511                noteStr = ReplaceNumberByKey("BOX", noteStr, pass+1, "=", ";")
1512                Note/K I_ext
1513                Note I_ext , noteStr
1514//              Print "box = ",noteStr
1515        endif
1516
1517        NVAR sParam = gSmoothFac                //already in the right DF
1518       
1519        ControlInfo/W=Desmear_Graph DSMControl_3c               //SSCheck
1520        if(V_value == 1)
1521//              Interpolate2/T=3/N=(nq)/I=2/F=1/SWAV=S_ext/Y=Yi_SS/X=Yq_SS Q_ext, I_ext         //Igor 5
1522//              Interpolate/T=3/N=(nq)/I=2/F=1/S=S_ext/Y=Yi_SS/X=Yq_SS I_ext /X=Q_ext                   //Igor 4
1523        //Igor 4
1524                String str=""
1525                nq_ext = numpnts(Q_ext)
1526                str = "Interpolate/T=3/N=("+num2str(nq_ext)+")/I=1/F=("+num2str(sParam)+")/Y=Yi_SS/X=Yq_SS I_ext /X=Q_ext"             
1527                Execute str
1528//              Print Str
1529//              Interpolate2/T=3/N=(nq_ext)/I=1/F=(sParam)/Y=Yi_SS/X=Yq_SS Q_ext, I_ext
1530        // end Igor 4   
1531                wave yi_ss = yi_ss              // already in the right DF
1532                wave yq_ss = yq_ss
1533                // reassign the "working" waves with the result of interpolate, which has the same I/Q values
1534                I_ext = yi_ss
1535                Q_ext = yq_ss
1536               
1537                noteStr=note(I_ext)
1538                pass = NumberByKey("SPLINE", noteStr, "=", ";")
1539                noteStr = ReplaceNumberByKey("SPLINE", noteStr, pass+1, "=", ";")
1540                Note/K I_ext
1541                Note I_ext , noteStr
1542//              Print "spline = ",noteStr
1543        endif
1544       
1545        //undo the scaling
1546        If(doLog)
1547                I_ext -= offset
1548                I_ext = 10^I_ext
1549        endif
1550       
1551        // at this point, I_ext has too many points - and we need to just return the
1552        // center chunk that is the original q-values
1553        // as assign this to the working set for the desmear step
1554        // and to the _smth set in case another smoothng pass is desired
1555        // Q_smth has not changed, S_smth has not changed
1556        I_smth = interp(Q_smth[p], Q_ext, I_ext )
1557       
1558        Note/K I_smth
1559        Note I_smth , noteStr
1560//      Print "end of smoothed, note = ",note(I_smth)
1561       
1562        Variable nq = numpnts($(USANSFolder+":DSM:Q_smth"))
1563//      Print "nq after smoothing = ",nq
1564
1565        //reset the global
1566        NVAR gNq = gNq
1567        gNq = nq
1568        //report the chi^2 difference between the smoothed curve and the experimental data
1569        NVAR chi2 = gChi2Smooth
1570        chi2 = SmoothedChi2(I_smth)
1571       
1572        Execute "AppendSmoothed()"
1573       
1574        setDataFolder root:
1575        return(0)
1576End
1577
1578// undo the smoothing and start over - useful if you've smoothed
1579// too aggressively and need to back off
1580Function DSM_SmoothUndoButtonProc(ctrlName) : ButtonControl
1581        String ctrlName
1582
1583        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder       
1584       
1585        Execute "RemoveSmoothed()"
1586        SetDataFolder $(USANSFolder+":DSM")
1587        Killwaves/Z I_smth,Q_smth,S_smth,Q_ext,I_ext,S_ext,Yi_SS,Yq_SS
1588        SetDataFolder root:
1589        return (0)
1590end
1591
1592//calculate the chi^2 value for the smoothed data
1593Function SmoothedChi2(I_smth)
1594        Wave I_smth
1595       
1596        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder       
1597       
1598        //start from the "msk", if they exist
1599        if(exists("I_msk")==1 && exists("Q_msk")==1 && exists("S_msk")==1)
1600                Wave iw = $(USANSFolder+":DSM:I_msk")
1601                Wave sw = $(USANSFolder+":DSM:S_msk")
1602        else
1603                //start from the "_exp" waves
1604                if(exists("I_exp")==1 && exists("Q_exp")==1 && exists("S_exp")==1)
1605                        Wave iw = $(USANSFolder+":DSM:I_exp")
1606                        Wave sw = $(USANSFolder+":DSM:S_exp")
1607                endif
1608        endif
1609       
1610        Variable ii,chi2,num
1611        chi2=0
1612        num = numpnts(iw)
1613        for(ii=0;ii<num;ii+=1)
1614                chi2 += (iw[ii] - I_smth[ii])^2 / (sw[ii])^2
1615        endfor
1616        Chi2 /= (num-1)
1617        return (chi2)
1618end
1619
1620// I_dsm is the desmeared data
1621//
1622// step (7) - desmearing is done, write out the result
1623//
1624Function DSM_SaveButtonProc(ctrlName) : ButtonControl
1625        String ctrlName
1626
1627        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder       
1628        NVAR useXMLOutput = root:Packages:NIST:gXML_Write
1629
1630        String saveStr
1631        SVAR curFile = $(USANSFolder+":DSM:gCurFile")
1632        saveStr = CleanupName((curFile),0)              //the output filename
1633        //
1634
1635        if (useXMLOutput == 1) 
1636                WriteXMLUSANSDesmeared(saveStr,0,0,1)
1637        else
1638                WriteUSANSDesmeared(saveStr,0,0,1)                      //use the full set (lo=hi=0) and present a dialog
1639        endif
1640       
1641        SetDataFolder root:
1642        return(0)
1643End
1644
1645Function DSM_HelpButtonProc(ctrlName) : ButtonControl
1646        String ctrlName
1647
1648        DisplayHelpTopic/Z/K=1 "Desmearing USANS Data"
1649        if(V_flag !=0)
1650                DoAlert 0,"The Desmearing USANS Data Help file could not be found"
1651        endif
1652        return(0)
1653End
1654
1655
1656//toggles the log/lin display of the loaded data set
1657Function DSM_LoadCheckProc(ctrlName,checked) : CheckBoxControl
1658        String ctrlName
1659        Variable checked
1660
1661        ModifyGraph log=(checked)
1662        return(0)
1663End
1664
1665
1666Function DSM_ExtrapolationCheckProc(ctrlName,checked) : CheckBoxControl
1667        String ctrlName
1668        Variable checked
1669
1670        if(checked)
1671                AppendExtrapolation()
1672        else
1673                RemoveExtrapolation()
1674        endif
1675        return(0)
1676End
1677
1678
1679// takes as input the "working waves"
1680//
1681// creates intermediate waves to work on
1682//
1683// output of Q_dsm,I_dsm,S_dsm (and I_dsm_sm, the result of smearing I_dsm)
1684//
1685Function DSM_DesmearButtonProc(ctrlName) : ButtonControl
1686        String ctrlName
1687       
1688        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder       
1689       
1690        SetDataFolder $(USANSFolder+":DSM")
1691        if(exists("I_smth")==1 && exists("Q_smth")==1 && exists("S_smth")==1)
1692                wave Q_smth , I_smth ,S_smth
1693                Duplicate/O I_smth,I_work,Q_work,S_work
1694                I_work = I_smth
1695                Q_work = Q_smth
1696                S_work = S_smth
1697        else
1698                //start from the "msk", creating work waves
1699                if(exists("I_msk")==1 && exists("Q_msk")==1 && exists("S_msk")==1)
1700                        wave Q_msk,I_msk,S_msk
1701                        Duplicate/O I_msk,I_work,Q_work,S_work
1702                        I_work = I_msk
1703                        Q_work = Q_msk
1704                        S_work = S_msk
1705                else
1706                        //start from the "_exp" waves
1707                        if(exists("I_exp")==1 && exists("Q_exp")==1 && exists("S_exp")==1)
1708                                wave Q_exp,I_exp,S_exp
1709                                Duplicate/O I_exp,I_work,Q_work,S_work
1710                                I_work = I_exp
1711                                Q_work = Q_exp
1712                                S_work = S_exp
1713                        endif
1714                endif
1715        endif
1716        //SetDataFolder root:
1717       
1718        NVAR nq = gNq
1719        NVAR m = gPowerM
1720        NVAR chi2_target = gChi2Target
1721        NVAR maxFastIter = gMaxFastIter
1722        NVAR maxSlowIter = gMaxSlowIter
1723       
1724        //      SET WEIGHTING OF EXPERIMENTAL DATA.
1725        Duplicate/O Q_work weights
1726        Wave weights = weights
1727        weights = 1/S_work^2
1728
1729//      calculate weighting array for smearing of data
1730        Make/O/D/N=(nq,nq) FW
1731        Wave FW
1732        Weights_L(m,FW,Q_work)
1733
1734//      ^^^^   Iterative desmearing   ^^^^*
1735        Variable chi2_old,chi2_new,done,iter
1736//      FOR 0TH ITERATION, EXPERIMENTAL DATA IS USED FOR Y_OLD, create ys_old for result
1737//      y_old = I_old, y_new = I_dsm, I_dsm_sm = ys_new,
1738// duplicate preserves the wave note!
1739        Duplicate/O I_work I_old,Is_old,I_dsm,I_dsm_sm
1740        Duplicate/O Q_work Q_dsm,S_dsm          //sets Q_dsm correctly
1741        wave S_dsm,I_old,Is_old,I_dsm,I_dsm_sm
1742        I_old = I_work
1743        Is_old = 0
1744        I_dsm = 0
1745        I_dsm_sm = 0
1746       
1747//      Smear 0TH iter guess Y --> YS
1748        DSM_Smear(I_old,Is_old,NQ,FW)
1749        chi2_OLD = chi2(Is_old,I_work,weights,NQ)
1750       
1751        printf "starting chi^2 = %g\r",chi2_old
1752        Print "Starting fast convergence..... "
1753
1754        done = 0                //false
1755        iter = 0
1756        Do                                      // while not done, use Fast convergence
1757                I_dsm = I_work * I_old / Is_old //        Calculate corrected guess (no need for do-loop)
1758
1759//        Smear iter guess I_dsm --> I_dsm_sm and see how well I_dsm_sm matches experimental data
1760                DSM_Smear(I_dsm,I_dsm_sm,NQ,FW)
1761                chi2_new = chi2(I_dsm_sm,I_work,weights,NQ)
1762
1763//        Stop iteration if fit from new iteration has worse fit...
1764                If (chi2_new > chi2_old)
1765                        Done = 1
1766                Endif
1767               
1768//        Stop iteration if fit is better than target value...
1769                If (chi2_new < chi2_target)
1770                        Done = 1
1771                Else
1772                        Iter += 1
1773                        Printf "Iteration %d, Chi^2(new) = %g\r", Iter,chi2_new
1774                        I_old = I_dsm
1775                        Is_old = I_dsm_sm
1776                        if(iter>maxFastIter)
1777                                break
1778                        endif
1779                        CHI2_OLD = CHI2_NEW
1780                EndIf
1781        while( !done )
1782       
1783        // append I_dsm,I_exp to the graph
1784        Execute "AppendDesmeared()"
1785        DoUpdate
1786       
1787        SetDataFolder $(USANSFolder+":DSM")
1788
1789       
1790// step (6) - refine the desmearing using slow convergence
1791        Print "Starting slow convergence..... "
1792        done = 0                //  ! reset flag for slow convergence
1793        Do
1794                I_dsm = I_old + (I_work - Is_old)       //        Calculate corrected guess
1795
1796//        Smear iter guess Y --> YS
1797                DSM_Smear(I_dsm,I_dsm_sm,NQ,FW)
1798                chi2_new = chi2(I_dsm_sm,I_work,weights,NQ)
1799
1800//        Stop iteration if fit from new iteration has worse fit...
1801                If (chi2_new > chi2_old)
1802                        Done = 1
1803                Endif
1804               
1805//        Stop iteration if fit is better than target value...
1806                If (chi2_new < chi2_target)
1807                        Done = 1
1808                Else
1809                        Iter += 1
1810                       
1811                        if(mod(iter, 50 ) ==0 )
1812                                Printf "Iteration %d, Chi^2(new) = %g\r", Iter,chi2_new
1813                                DoUpdate
1814                        endif
1815                        I_old = I_dsm
1816                        Is_old = I_dsm_sm
1817
1818                        CHI2_OLD = CHI2_NEW
1819                EndIf
1820                if(iter>maxSlowIter)
1821                        break
1822                endif
1823        While ( !done )
1824
1825        Printf "Iteration %d, Chi^2(new) = %g\r", Iter,chi2_new
1826
1827        // adjust the error
1828        SetDataFolder $(USANSFolder+":DSM")
1829        Duplicate/O S_work err
1830        S_dsm = abs(err/I_work*I_dsm)           //proportional error
1831//John simply keeps the same error as was read in from the smeared data set - is this right?
1832//      S_dsm = S_Work
1833       
1834        NVAR gChi =  gChi2Final         //chi^2 final
1835        NVAR gIter = gIterations                //total number of iterations
1836        gChi = chi2_new
1837        gIter = Iter
1838       
1839        SVAR str = gIterStr
1840        sprintf str,"%d iterations required",iter
1841       
1842        SetDataFolder root:
1843        return(0)
1844End
1845
1846Function DSM_RevertButtonProc(ctrlName) : ButtonControl
1847        String ctrlName
1848       
1849        SVAR USANSFolder = root:Packages:NIST:USANS:Globals:gUSANSFolder       
1850       
1851       
1852        CleanUpJunk()
1853
1854        SetDataFolder $(USANSFolder+":DSM")
1855
1856        //reset the working waves to the original
1857        wave Q_exp_orig,I_exp_orig,S_exp_orig
1858
1859        Duplicate/O Q_exp_orig Q_exp
1860        Duplicate/O I_exp_orig I_exp
1861        Duplicate/O S_exp_orig S_exp
1862        // kill the data folder
1863        // re-initialize?
1864
1865        SetDataFolder root:
1866       
1867        return(0)
1868End
Note: See TracBrowser for help on using the repository browser.