source: sans/Dev/trunk/NCNR_User_Procedures/Analysis/Packages/GeneticOptimization/NCNR_GenFitUtils.ipf @ 764

Last change on this file since 764 was 764, checked in by srkline, 12 years ago
  • fixed a few bugs with GenCurveFit?, and how the reports are generated


  • the DEFAULT.MASK file is automatically loaded when the path is set, if it can be found. this only happens from the main (yellow) panel. Nothing happens if that exact file is not found.


  • a "Sector_PlusMinus" averaging option is added. This defines the LEFT sector as being "negative" q-values. Everything else behaves as a normal sector average. This is from Lionel, a very old ticket #31


  • if sectors or annular regions are drawn on RAW data files, the drawn lines are re-drawn correctly as the data is scrolled using the < and > buttons.


  • a super secret option for a "histogram pair" has been added. May be useful for alignment, may ditch if Jeff and Cedric don't like it. To do this, put cursor A on the 2D image at the center of where you want the vertical and horizontal swath to be. +-5 pixels is hard-wired. draw any marquee(size, location is ignored) and select SANS Histogram, and you get the pair. If cursor A is not on the graph, you get the normal histogram as defined by the marquee.


  • arrow buttons on RAW 2D data display now search +- 10 data files for "next", in case there are missing file numbers.


  • Incorporated Lionel's changes to ILL_* files for his generation of a "DIV" file for D22


  • Added the offset traces checkbox back to the SASCALC panel. previously it was hidden on the simulation panels.


  • loosened the tolerance for SDD matching onn the MRED panel to 0.1 m



File size: 9.8 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma IgorVersion=6.1
3
4// genetic optimization, uses XOP supplied by Andy Nelson, ANSTO
5// http://www.igorexchange.com/project/gencurvefit
6
7
8
9// TO USE GENETIC OPTIMIZATION
10//      Variable/G root:Packages:NIST:gUseGenCurveFit = 0                       //set to 1 to use genetic optimization
11// -- this flag is set by a menu item SANS Models->Packages->Enable Genetic Optimization
12//
13// ** it is currently only available for single fits - not for global fits (even the simple ones)
14// incorporating into WM's global fit would be u-g-l-y
15//
16//
17//  to complete the addition of genetic curve fitting:
18//
19// X add a check to make sure that the XOP is installed before the switch is set (force 0 if not present)
20// X add a global variable as a switch
21// X parse the limits. All must be filled in. If not, fit aborts and asks for user input to fill them in. Limits
22//   on fixed parameters are +/- 1% of the value. Has no effect on fit (duh), but filled in for completeness.
23// X create a mask wave for use when cursors are selected. [a,b] subranges can't be used w/Andy's XOP
24// X fitYw not behaving correctly - probably need to hand-trim
25// X use the switch in the wrapper, building the structure and function call as necessary
26// X be sure that the smeared function name is printed out as it's used, not the generic wrapper
27// X test for speed. the smeared fit is especially SLOW, WAY slower than it should be...AAO vs. point function??
28// X decide which options to add (/N /DUMP /TOL, robust fitting, etc - see Andy's list
29// X add the XOP to the distribution, or instructions (better to NOT bundle...)
30// X odd bug where first "fit" fails on AppendToGraph as GenCurveFit is started. May need to disable /D flag
31// X- need to pass back the chi-squared and number of points. "V_" globals don't appear
32// -- add the flags to calculate the residuals (/R), and then manually append the residual wave to the graph.
33//
34//
35// for the speed test. try writing my own wrapper for an unsmeared calculation, and see if it's still dog-slow.
36// --- NOPE, the wrapper is not a problem, tested this, and they seem to be both the same speed, each only about 5 seconds.
37// -- timing results for fitting apoferritin:
38//
39// L-M method, unsmeared: 0.95 s
40// L-M method, smeared: 5.85 s
41//
42// Genetic method, unsmeared: 7.32 s (2199 function evaluations) = 0.0033 sec/eval
43// Genetic method, smeared: 416 s (2830 function evaluations x20 for smearing) = 0.0074 sec/eval !
44//
45// -- even correcting the Gen-smeared fit for the 20pt quadrature, calculations there are 2x slower than
46// the same unsmeared fit. Why?? Both converge in the same number of iterations (~30 to 40). The number of function
47// evaluations is different, due to the random start and random mutations. Setting the seed is unlikely
48// to change the results.
49
50Static Constant kGenOp_tol=0.001
51
52
53Function Init_GenOp()
54        if(!exists("GenCurveFit"))
55                DoAlert 1,"The genetic optimiztion XOP is not installed. Do you want to open the web page to download the installer?"
56                if(V_flag == 1)
57                        BrowseURL "http://www.igorexchange.com/project/gencurvefit"
58                endif
59        else
60                DoAlert 0,"Genetic Optimization has been enabled."
61                Variable/G root:Packages:NIST:gUseGenCurveFit = 1                       //set to 1 to use genetic optimization
62        endif
63        BuildMenu "SANS Models"
64End
65
66// uncheck the flag, and change the menu
67Function UnSet_GenOp()
68        DoAlert 0,"Genetic Optimization has been disabled"
69        Variable/G root:Packages:NIST:gUseGenCurveFit = 0                       //set to 1 to use genetic optimization
70        BuildMenu "SANS Models"
71End
72
73Function/S GenOpFlagEnable()
74        Variable flag = NumVarOrDefault("root:Packages:NIST:gUseGenCurveFit",0)
75//      NVAR/Z flag = root:Packages:NIST:gUseGenCurveFit
76//      if(!NVAR_Exists(flag))
77//              return("")              //to catch the initial menu build that occurs before globals are created
78//      endif
79       
80        if(flag)
81                return("!"+num2char(18) + " ")
82        else
83                return("")
84        endif
85        BuildMenu "SANS Models"
86end
87// this is the default selection if nvar does not exist
88Function/S GenOpFlagDisable()
89        Variable flag = NumVarOrDefault("root:Packages:NIST:gUseGenCurveFit",0)
90
91//      NVAR/Z flag = root:Packages:NIST:gUseGenCurveFit
92//      if(!NVAR_Exists(flag))
93//              Variable/G root:Packages:NIST:gUseGenCurveFit = 0
94//      endif
95       
96        if(!flag)
97                return("!"+num2char(18) + " ")
98        else
99                return("")
100        endif
101        BuildMenu "SANS Models"
102end
103
104
105
106// the structure must be named fitFuncStruct, or the XOP will report an error and not run
107//
108Structure fitFuncStruct   
109        Wave w
110        wave y
111        wave x[50]
112        int16 numVarMD
113        wave ffsWaves[50]
114        wave ffsTextWaves[10]
115        variable ffsvar[5]
116        string ffsstr[5]
117        nvar ffsnvars[5]
118        svar ffssvars[5]
119        funcref SANSModelAAO_proto ffsfuncrefs[10]              //this is an AAO format
120        uint32 ffsversion    // Structure version.
121EndStructure
122
123Function GeneticFit_SmearedModel(s) : FitFunc
124        Struct fitFuncStruct &s
125
126        FUNCREF SANSModelSTRUCT_proto foo=$s.ffsstr[0]
127        NVAR num = root:num_evals
128       
129        STRUCT ResSmearAAOStruct fs
130        WAVE fs.coefW = s.w     
131        WAVE fs.yW = s.y
132        WAVE fs.xW = s.x[0]
133        WAVE fs.resW = s.ffsWaves[0]
134       
135        Variable err
136        err = foo(fs)           //this is the smeared STRUCT function
137               
138        num += 1
139        return(0)
140End
141
142Function GeneticFit_UnSmearedModel(s) : FitFunc
143        Struct fitFuncStruct &s
144
145        FUNCREF SANSModelAAO_proto foo=$s.ffsstr[0]
146        NVAR num = root:num_evals
147
148        foo(s.w,s.y,s.x[0])                     //this is the unsmeared function
149       
150        num += 1
151       
152        return(0)
153End
154
155// need to pass back the chi-squared and number of points. "V_" globals don't appear
156//
157// function will only compile if the GenCurveFit XOP is installed - else it will return zero
158//
159Function DoGenCurveFit(useRes,useCursors,sw,fitYw,fs,funcStr,holdStr,val,lolim,hilim,pt1,pt2)
160        Variable useRes,useCursors
161        WAVE sw,fitYw
162        STRUCT ResSmearAAOStruct &fs
163        String &funcStr,holdStr
164        Variable &val
165        WAVE/T lolim,hilim
166        Variable pt1,pt2                //already sorted if cursors are needed
167
168#if exists("GenCurveFit")
169
170        // initialise the structure you will use
171        struct fitFuncStruct bar
172
173        // we must set the version of the structure (currently 1000)
174        bar.ffsversion = 1000
175       
176        // numVarMD is the number of dependent variables you are fitting
177        // this must be correct, or Gencurvefit won't run.
178        bar.numVarMD=1         
179
180        // fill in the details and waves that I need
181        bar.ffsstr[0] = funcStr //generate the reference as needed for smeared or unsmeared
182        WAVE bar.w = fs.coefW
183        WAVE bar.y =fs.yW
184        WAVE bar.x[0] = fs.xW
185        WAVE/Z bar.ffsWaves[0] = fs.resW                //will not exist for 3-column data sets
186       
187
188        //need to parse limits, or make up some defaults
189        // limits is (n,2)
190        Variable nPnts = numpnts(fs.coefW),i,multip=1.01,isUSANS=0,tol=0.01
191        Make/O/D/N=(nPnts,2) limits
192        Wave limits=limits
193        for (i=0; i < nPnts; i += 1)
194       
195                if (strlen(lolim[i]) > 0)
196                        limits[i][0] = str2num(lolim[i])
197                else
198                        if(cmpstr(holdStr[i],"0")==0)           //no limit, not held
199                                Abort "You must enter low and high coefficient limits for all free parameters"
200                        else
201                                limits[i][0] = fs.coefW[i]/multip               //fixed parameter, just stick something in
202                        endif
203                endif
204               
205                if (strlen(hilim[i]) > 0)
206                        limits[i][1] = str2num(hilim[i])
207                else
208                        if(cmpstr(holdStr[i],"0")==0)           //no limit, not held
209                                Abort "You must enter low and high coefficient limits for all free parameters"
210                        else   
211                                limits[i][1] = fs.coefW[i] * multip
212                        endif
213                endif
214        endfor
215
216        if (dimsize(fs.resW,1) > 4)
217                isUSANS = 1
218        endif
219       
220//      generate a mask wave if needed (1=use, 0=mask)
221// currently, the mask is not used, since smeared USANS is not handled correctly
222// temporary, trimmed data sets are used instead
223        if(useCursors)
224                npnts = numpnts(fs.xW)
225//              Make/O/D/N=(npnts) GenOpMask
226//              Wave GenOpMask=GenOpMask
227//              GenOpMask = 1
228//              for(i=0;i<pt1;i+=1)
229//                      GenOpMask[i] = 0
230//              endfor
231//              for(i=pt2;i<npnts-1;i+=1)
232//                      GenOpMask[i] = 0
233//              endfor
234
235                Redimension/N=(pt2-pt1+1) fitYw
236               
237                Make/O/D/N=(pt2-pt1+1) trimY,trimX,trimS
238                WAVE trimY=trimY
239                trimY = fs.yW[p+pt1]
240                WAVE trimX=trimX
241                trimX = fs.xW[p+pt1]
242                WAVE trimS=trimS
243                trimS = sw[p+pt1]
244                //trim all of the waves, don't use the mask
245                WAVE bar.y = trimY
246                WAVE bar.x[0] = trimX
247               
248        endif   
249
250        Variable t0 = stopMStimer(-2)
251
252
253       
254        Variable/G root:num_evals               //for my own tracking
255        NVAR num = root:num_evals
256        num=0
257
258       
259        // other useful flags:  /N /DUMP /TOL /D=fitYw
260        //  /OPT=1 seems to make no difference whether it's used or not
261        // /N does not speed anything up at all, and you get no feedback
262        // /R does work, generating "res_" wave, but the append must be "manual"
263       
264        // append the fit
265        //do this only because GenCurveFit tries to append too quickly?
266        String traces=TraceNameList("", ";", 1 )                //"" as first parameter == look on the target graph
267        if(strsearch(traces,"FitYw",0) == -1)
268                if(useCursors)
269                        AppendtoGraph fitYw vs trimX
270                else
271                        AppendToGraph FitYw vs fs.xw
272                endif
273        else
274                RemoveFromGraph FitYw
275                if(useCursors)
276                        AppendtoGraph fitYw vs trimX
277                else
278                        AppendToGraph FitYw vs fs.xw
279                endif
280        endif
281        ModifyGraph lsize(FitYw)=2,rgb(FitYw)=(0,0,0)
282
283        do
284                       
285                if(useRes && useCursors)
286                        GenCurveFit/MAT /STRC=bar /X=bar.x[0] /I=1 /TOL=(kGenOp_tol) /W=trimS /D=fitYw GeneticFit_SmearedModel,bar.y,bar.w,holdStr,limits
287                        break
288                endif
289                if(useRes)
290                        GenCurveFit/MAT /STRC=bar /X=bar.x[0] /I=1 /TOL=(kGenOp_tol) /W=sw /D=fitYw /R GeneticFit_SmearedModel,bar.y,bar.w,holdStr,limits
291                        break
292                endif
293               
294                //no resolution
295                if(!useRes && useCursors)
296                        GenCurveFit/MAT /STRC=bar /X=bar.x[0] /I=1 /TOL=(kGenOp_tol) /W=trimS /D=fitYw GeneticFit_UnSmearedModel,bar.y,bar.w,holdStr,limits
297                        break
298                endif
299                if(!useRes)
300                        GenCurveFit/MAT /STRC=bar /X=bar.x[0] /I=1 /TOL=(kGenOp_tol) /W=sw /D=fitYw GeneticFit_UnSmearedModel,bar.y,bar.w,holdStr,limits
301                        break
302                endif
303               
304        while(0)       
305       
306//      NVAR V_chisq = V_chisq
307//      NVAR V_npnts = V_npnts
308//      NVAR V_fitIters = V_fitIters
309        WAVE/Z W_sigma = W_sigma
310       
311        val = V_npnts           //return this as a parameter
312       
313        t0 = (stopMSTimer(-2) - t0)*1e-6
314        Printf  "fit time = %g seconds\r\r",t0
315        Print W_sigma   
316        Print "number of iterations = ",V_fitIters
317        Print "number of function evaluations = ",num
318        Print "Chi-squared = ",V_chisq
319       
320        return(V_chisq)
321#else
322        return(0)
323#endif 
324end
Note: See TracBrowser for help on using the repository browser.