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

Last change on this file since 495 was 495, checked in by srkline, 14 years ago

Added a procedure file that does the necessary wrapping for GenCurveFit?, since it's not a perfect drop-in replacement for FuncFit?. Required modification of the FitWrapper? to switch to GenCurveFit? as needed.
Switch between regular L-M and GenOp? using a menu item.a (sets a gobal)
Still ridiculously slow to use.
Can't yet be used with global fitting. Would be a real pain to implement. Can't imagine how slow that would be to use...

Bug fixes in PatchFiles? (default button for filter type) and Correct (use tolerance of +/- 0.01 pixel for determining of what is a "mismatch" of the beam centers. Problem cropped up with ICE, but should be fixed anyways)

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