source: sans/Analysis/branches/ajj_23APR07/IGOR_Package_Files/Put in User Procedures/SANS_Models_v3.00/Packages/Wrapper.ipf @ 198

Last change on this file since 198 was 198, checked in by srkline, 15 years ago

Adding three new 2D functions, the easy ones that use a Gaussian distribution of parameters.

Changed the parsing of constraints to only build a constraint wave for those parameters that are not being held. failing to do so results in an "unknown error" from curve fitting. This fix was done in both the 1D and 2D wrappers.

Changed the default mask that was two pixels all around to now mask out the beamstop for 2D data sets. 8 pixel radius is currently hard-wired in PlotUtils2D - and is generated as the fit is dispatched, automatically determining the beam center from the data set.

File size: 29.1 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma IgorVersion=6.0
3
4//
5// need a way of importing more functions into the experiment
6// ? call the picker panel from the panel?
7//
8//
9
10//Macro OpenWrapperPanel()
11//      Init_WrapperPanel()
12//End
13
14Function Init_WrapperPanel()
15        DoWindow/F WrapperPanel
16        if(V_flag==0)
17                if(exists("root:coefKWStr")==0)
18                        String/G root:coefKWStr=""
19                endif
20                if(exists("root:suffixKWStr")==0)
21                        String/G root:suffixKWStr=""
22                endif
23                Execute "WrapperPanel()"
24        endif
25End
26
27////////
28//
29// if model is Smeared, search the DF for coefficients
30// if new DF chosen, need to reset
31// if new model function, need to reset table
32//
33// create hold_mod (0/1), constr_low_mod, constr_hi_mod
34// in either DF (smeared) or in root: (normal)
35// and put these in the table as needed
36//
37Window WrapperPanel()
38        PauseUpdate; Silent 1           // building window...
39        NewPanel /W=(459,44,1113,499)/N=wrapperPanel/K=1 as "Curve Fit Setup"
40        ModifyPanel fixedSize=1
41       
42        GroupBox grpBox_0,pos={18,11},size={390,113}
43        GroupBox grpBox_1,pos={426,10},size={207,113}
44        GroupBox grpBox_2 title="No Fit",pos={10,130},size={620,1},frame=0,fSize=10,fstyle=1,fColor=(39321,1,1)
45        GroupBox grpBox_3 title="",pos={10,150},size={620,1},frame=0,fSize=10,fstyle=1,fColor=(39321,1,1)
46
47        Button button_1,pos={280,57},size={120,20},proc=PlotModelFunction,title="Plot 1D Function"
48        Button button_2,pos={300,93},size={100,20},proc=AppendModelToTarget,title="Append 1D"
49        Button button_3,pos={300,20},size={100,20},proc=W_LoadDataButtonProc,title="Load 1D Data"
50        PopupMenu popup_0,pos={30,21},size={218,20},title="Data Set"
51        PopupMenu popup_0,mode=1,value= #"W_DataSetPopupList()"
52        PopupMenu popup_1,pos={30,57},size={136,20},title="Function"
53        PopupMenu popup_1,mode=1,value= #"W_FunctionPopupList()",proc=Function_PopMenuProc
54        PopupMenu popup_2,pos={30,93},size={123,20},title="Coefficients"
55        PopupMenu popup_2,mode=1,value= #"W_CoefPopupList()",proc=Coef_PopMenuProc
56        CheckBox check_0,pos={440,19},size={79,14},title="Use Cursors?",value= 0
57        CheckBox check_1,pos={440,42},size={74,14},title="Use Epsilon?",value= 0
58        CheckBox check_2,pos={440,65},size={95,14},title="Use Constraints?",value= 0
59        CheckBox check_3,pos={530,18},size={72,14},title="2D Functions?",value= 0
60        CheckBox check_3 proc=Toggle2DControlsCheckProc
61        CheckBox check_4,pos={440,85},size={72,14},title="Report?",value= 0
62        CheckBox check_5,pos={454,103},size={72,14},title="Save it?",value= 0
63        //change draw order to put button over text of checkbox
64        Button button_0,pos={520,93},size={100,20},proc=DoTheFitButton,title="Do 1D Fit"
65
66        Edit/W=(20,174,634,435)/HOST=# 
67        ModifyTable width(Point)=0
68        RenameWindow #,T0
69        SetActiveSubwindow ##
70EndMacro
71
72//obvious use
73Function W_LoadDataButtonProc(ba) : ButtonControl
74        STRUCT WMButtonAction &ba
75
76        switch( ba.eventCode )
77                case 2: // mouse up
78                        // click code here
79                        String  topGraph= WinName(0,1)
80                        if(strlen(topGraph) != 0)
81                                DoWindow/F $topGraph                    //so that the panel is not on top
82                        endif
83                        Execute "A_LoadOneDData()"
84                        break
85        endswitch
86
87        ControlUpdate/W=WrapperPanel popup_0
88        return 0
89End
90
91
92// is there a simpler way to do this?
93Function/S W_DataSetPopupList()
94
95        String str=GetAList(4),tmp="",onTargetStr=""
96        Variable ii
97//      ControlInfo/W=WrapperPanel check_3
98//      if(V_Value==1)          //if "from target" checked
99//              //ther must be a better way to do this
100//              onTargetStr = TraceNameList("",";",1)
101//              onTargetStr = ReplaceString("_i",onTargetStr,"")                //get rid of the "_i"
102//              for(ii=0;ii<ItemsInList(onTargetStr);ii+=1)
103//                      if(WhichListItem(StringFromList(ii,onTargetStr,";"), str  , ";") != -1)
104//                              tmp = Addlistitem(StringFromList(ii,onTargetStr,";"),tmp)               //only keep the matches w/data folder listing
105//                      endif
106//              endfor
107//              return(tmp)
108//      endif
109
110        if(strlen(str)==0)
111                str = "No data loaded"
112        endif
113        str = SortList(str)
114       
115        return(str)
116End
117
118
119// show the available models
120// not the f*(cw,xw) point calculations
121// not the *X(cw,xw) XOPS
122//
123// KIND:10 should show only user-defined curve fitting functions
124// - not XOPs
125// - not other user-defined functions
126Function/S W_FunctionPopupList()
127        String list,tmp
128        list = FunctionList("*",";","KIND:10")          //get every user defined curve fit function
129
130        //now start to remove everything the user doesn't need to see...
131               
132        tmp = FunctionList("*_proto",";","KIND:10")             //prototypes
133        list = RemoveFromList(tmp, list  ,";")
134        //prototypes that show up if GF is loaded
135        list = RemoveFromList("GFFitFuncTemplate", list)
136        list = RemoveFromList("GFFitAllAtOnceTemplate", list)
137        list = RemoveFromList("NewGlblFitFunc", list)
138        list = RemoveFromList("NewGlblFitFuncAllAtOnce", list)
139        list = RemoveFromList("GlobalFitFunc", list)
140        list = RemoveFromList("GlobalFitAllAtOnce", list)
141        list = RemoveFromList("GFFitAAOStructTemplate", list)
142        list = RemoveFromList("NewGF_SetXWaveInList", list)
143        list = RemoveFromList("NewGlblFitFuncAAOStruct", list)
144       
145        // more to remove as a result of 2D/Gizmo
146        list = RemoveFromList("A_WMRunLessThanDelta", list)
147        list = RemoveFromList("WMFindNaNValue", list)
148        list = RemoveFromList("WM_Make3DBarChartParametricWave", list)
149        list = RemoveFromList("UpdateQxQy2Mat", list)
150       
151
152        tmp = FunctionList("f*",";","NPARAMS:2")                //point calculations
153        list = RemoveFromList(tmp, list  ,";")
154       
155        tmp = FunctionList("fSmear*",";","NPARAMS:3")           //smeared dependency calculations
156        list = RemoveFromList(tmp, list  ,";")
157       
158//      tmp = FunctionList("*X",";","KIND:4")           //XOPs, but these shouldn't show up if KIND:10 is used initially
159//      Print "X* = ",tmp
160//      print " "
161//      list = RemoveFromList(tmp, list  ,";")
162       
163        //non-fit functions that I can't seem to filter out
164        list = RemoveFromList("BinaryHS_PSF11;BinaryHS_PSF12;BinaryHS_PSF22;EllipCyl_Integrand;PP_Inner;PP_Outer;Phi_EC;TaE_Inner;TaE_Outer;",list,";")
165
166        if(strlen(list)==0)
167                list = "No functions plotted"
168        endif
169       
170        list = SortList(list)
171        return(list)
172End
173
174
175// show all the appropriate coefficient waves
176//
177// also need to search the folder listed in "data set" popup
178// for smeared coefs
179//
180// - or - restrict the coefficient list based on the model function
181// - new way, filter the possible values based on the data folder and function
182Function/S W_CoefPopupList()
183
184        String notPlotted="Please plot the function"
185        ControlInfo/W=wrapperpanel popup_1
186        String funcStr=S_Value
187        String coefStr=getFunctionCoef(funcStr)
188       
189        if(cmpstr(coefStr,"")==0)               //no correspondence in the KW string
190                return(notPlotted)
191        endif
192       
193       
194        //found a coefficient wave - only two places to look
195        // is it in the root folder?
196        if(exists("root:"+coefStr) != 0)
197                return(coefStr)
198        endif
199       
200        // is it in the data folder?
201        ControlInfo/W=wrapperpanel popup_0
202        String folderStr=S_Value
203        if(exists("root:"+folderStr+":"+coefStr) != 0)
204                return(coefStr)
205        endif
206
207        return(notPlotted)
208End
209
210// show all the appropriate coefficient waves
211//
212// also need to search the folder listed in "data set" popup
213// for smeared coefs
214//
215// - or - restrict the coefficient list based on the model function
216//
217// --old way
218//Function/S W_CoefPopupList()
219//      String list
220//      setDataFolder root:
221//      list = WaveList("coef*",";","")
222//     
223//      ControlInfo/W=wrapperpanel popup_0
224//      if(V_Value != 0)                //0== no items in menu
225//              if(DataFolderExists("root:"+S_Value))
226//                      SetDataFolder $("root:"+S_Value)
227//                      list += WaveList("*coef*",";","")
228//              endif
229//      endif
230//     
231//      // tmp coefficients that aren't being cleaned up from somewhere...
232//      list = RemoveFromList("temp_coef_1;temp_coef_2;", list  ,";")
233//
234//      if(strlen(list)==0)
235//              list = "No functions plotted"
236//      endif
237//      list = SortList(list)
238//     
239////    Print itemsinlist(list,";")
240//     
241//      setDataFolder root:
242//      return(list)
243//End
244
245// if the coefficients are changed, then update the table
246//
247//update the table
248// may be easier to just kill the subwindow (table) and create a new one
249// need to set/reset all of the waves in the table
250//
251// !! only respond to mouse up
252//
253Function Coef_PopMenuProc(pa) : PopupMenuControl
254        STRUCT WMPopupAction &pa
255
256        switch( pa.eventCode )
257                case 2: // mouse up
258                        Variable popNum = pa.popNum
259                        String popStr = pa.popStr
260                        String suffix = getModelSuffix(popStr)
261                        ControlInfo/W=WrapperPanel popup_0
262                        String folderStr=S_Value
263                       
264                        if(cmpstr(popStr,"Please plot the function")==0)
265//                              Print "function not plotted"
266                                return(0)
267                        endif
268
269// this if/else/endif should not ever return an error alert     
270// it should simply set the data folder properly       
271                        if(DataFolderExists("root:"+folderStr))
272                                SetDataFolder $("root:"+folderStr)
273                                if(!exists(popStr))
274                                        // must be unsmeared model, work in the root folder
275                                        SetDataFolder root:                             
276                                        if(!exists(popStr))             //this should be fine if the coef filter is working, but check anyhow
277                                                DoAlert 0,"the coefficient and data sets do not match (1)"
278                                                return 0
279                                        endif
280                                endif
281                        else
282                                // must be unsmeared model, work in the root folder
283                                SetDataFolder root:     
284                                if(!exists(popStr))             //this should be fine if the coef filter is working, but check anyhow
285                                        DoAlert 0,"the coefficient and data sets do not match (2)"
286                                        return 0
287                                endif
288                        endif
289                       
290                        // farm the work out to another function?
291                        Variable num=numpnts($popStr)
292                        // make the necessary waves
293                        Make/O/D/N=(num) $("epsilon_"+suffix),$("Hold_"+suffix)
294                        Make/O/T/N=(num) $("LoLim_"+suffix),$("HiLim_"+suffix)
295                       
296                        // default epsilon values, sometimes needed for the fit
297                        Wave eps = $("epsilon_"+suffix)
298                        Wave coef=$popStr
299                        eps = abs(coef*1e-4) + 1e-10                    //default eps is proportional to the coefficients
300                        WAVE/T LoLim = $("LoLim_"+suffix)
301                        WAVE/T HiLim = $("HiLim_"+suffix)
302                        LoLim = ""              //should have nicer way of keeping the previous values
303                        HiLim = ""
304                       
305                        // clear the table (a subwindow)
306                        KillWindow wrapperPanel#T0
307                        Edit/W=(20,174,634,435)/HOST=#
308                        RenameWindow #,T0
309                        // get them onto the table
310                        // how do I get the parameter name?
311                        String param = WaveList("*param*_"+suffix, "", "TEXT:1," )              //this is *hopefully* one wave
312                        AppendtoTable/W=wrapperPanel#T0 $param,$(popStr)
313                        AppendToTable/W=wrapperPanel#T0 $("Hold_"+suffix),$("LoLim_"+suffix),$("HiLim_"+suffix),$("epsilon_"+suffix)
314                        ModifyTable width(Point)=0
315                       
316                        SetDataFolder root:
317                        break
318        endswitch
319
320        return 0
321End
322
323// if the Function is changed, then update the coef popup (if possible) and then the table (if possible)
324//
325// !! only respond to mouse up
326//
327Function Function_PopMenuProc(pa) : PopupMenuControl
328        STRUCT WMPopupAction &pa
329
330        switch( pa.eventCode )
331                case 2: // mouse up
332                        Variable popNum = pa.popNum
333                        String funcStr = pa.popStr
334                        String coefStr = W_CoefPopupList()
335                       
336//                      Print "coefStr = ",coefStr
337                       
338                        ControlInfo/W=WrapperPanel popup_0
339                        String folderStr=S_Value
340                       
341                        String listStr = W_CoefPopupList()
342                        Variable num=WhichListItem(coefStr, listStr, ";")
343                        String str=StringFromList(num, listStr  ,";")
344//                      print "str = ",str
345                        //set the item in the coef popup, and pop it
346                        PopupMenu popup_2 mode=(num+1)
347                       
348                        Struct WMPopupAction ps
349                        ps.eventCode = 2                //fake mouse up
350                        ps.popStr = str
351                        Coef_PopMenuProc(ps)
352                       
353                        SetDataFolder root:
354                        break
355        endswitch
356
357        return 0
358End
359
360
361// always pass this the coefficient string
362//
363// either "coef_"
364// or "smear_coef_"
365//
366Function/S getFunctionCoef(funcStr)
367        String funcStr
368
369        SVAR listStr=root:coefKWStr
370        String coefStr = StringByKey(funcStr, listStr  ,"=",";",0)
371
372        return(coefStr)
373End
374
375// always pass this the coefficient string
376//
377// either "coef_"
378// or "smear_coef_"
379//
380// does NOT return the leading "_" as part of the suffix
381Function/S getModelSuffix(coefStr)
382        String coefStr
383
384        SVAR listStr=root:suffixKWStr
385        String suffixStr = StringByKey(coefStr, listStr  ,"=",";",0)
386
387        return(suffixStr)
388//      Variable pos,start=0
389
390//      if(stringmatch(coefStr,"smear_*") == 1)
391//              start=7 //look forwards to find "_", skipping "smear_coe" if necessary
392//      endif
393//      pos=Strsearch(coefStr,"_",start,0)
394        //Print start, pos
395//      return(coefStr[pos,strlen(coefStr)-1])
396End
397
398
399
400// - this is based on stringent "PlotNNN" naming requirements
401//
402//  ???
403// - how to kill the generated table and graph, that are not needed now
404//
405Function PlotModelFunction(ba) : ButtonControl
406        STRUCT WMButtonAction &ba
407
408        String folderStr,funcStr,coefStr,cmdStr=""
409        Variable useCursors,useEps,useConstr
410       
411        switch( ba.eventCode )
412                case 2: // mouse up
413                        ControlInfo/W=WrapperPanel popup_0
414                        folderStr=S_Value
415                       
416                        ControlInfo/W=WrapperPanel popup_1
417                        funcStr=S_Value
418                       
419                        // check for smeared or smeared function
420                        if(stringmatch(funcStr, "Smear*" )==1)
421                                //it's a smeared model
422                                // check for the special case of RPA that has an extra parameter
423                                if(strsearch(funcStr, "RPAForm", 0 ,0) == -1)
424                                        sprintf cmdStr, "Plot%s(\"%s\")",funcStr,folderStr              //not RPA
425                                else
426                                        sprintf cmdStr, "Plot%s(\"%s\",)",funcStr,folderStr             //yes RPA, leave a comma for input
427                                endif
428                        else
429                                // it's not,                   
430                                sprintf cmdStr, "Plot%s()",funcStr
431                        endif
432                       
433                        //Print cmdStr
434                        Execute cmdStr
435                       
436                        //pop the function menu to set the proper coefficients
437                        DoWindow/F WrapperPanel
438                        STRUCT WMPopupAction pa
439                        pa.popStr = funcStr
440                        pa.eventcode = 2
441                        Function_PopMenuProc(pa)
442       
443                        break
444        endswitch
445       
446        return 0
447End
448
449// How to bypass the step of plot and append?
450//
451// do it in two separate events
452//
453Function AppendModelToTarget(ba) : ButtonControl
454        STRUCT WMButtonAction &ba
455
456        String coefStr,suffix,yWStr,xWStr,folderStr
457       
458        switch( ba.eventCode )
459                case 2: // mouse up                     
460                        ControlInfo/W=WrapperPanel popup_2
461                        coefStr=S_Value
462                        suffix = getModelSuffix(coefStr)
463                       
464                        // check for smeared or smeared function
465                        if(stringmatch(coefStr, "smear*" )==1)
466                                //it's a smeared model
467                                ControlInfo/W=WrapperPanel popup_0
468                                folderStr=S_Value
469                                xWStr = "root:"+folderStr+":smeared_qvals"
470                                ywStr = "root:"+folderStr+":smeared_"+suffix
471                        else
472                                // it's not, so it's in the root folder
473                                xWStr = "xwave_"+suffix
474                                yWStr = "ywave_"+suffix
475                        endif
476                       
477                        Wave/Z yw = $yWStr
478                        Wave/Z xw = $xWStr
479                        if(WaveExists(yw) && WaveExists(xw))
480                                AppendtoGraph yw vs xw
481                        else
482                                DoAlert 0,"The selected model has not been plotted for the selected data set."
483                        endif
484                        break
485        endswitch
486       
487        return 0
488End
489
490
491// this should parse the panel and call the FitWrapper() function
492Function DoTheFitButton(ba) : ButtonControl
493        STRUCT WMButtonAction &ba
494
495        String folderStr,funcStr,coefStr
496        Variable useCursors,useEps,useConstr
497       
498        switch( ba.eventCode )
499                case 2: // mouse up
500                        ControlInfo/W=WrapperPanel popup_0
501                        folderStr=S_Value
502                       
503                        ControlInfo/W=WrapperPanel popup_1
504                        funcStr=S_Value
505                       
506                        ControlInfo/W=WrapperPanel popup_2
507                        coefStr=S_Value
508                       
509                        ControlInfo/W=WrapperPanel check_0
510                        useCursors=V_Value
511                        ControlInfo/W=WrapperPanel check_1
512                        useEps=V_Value
513                        ControlInfo/W=WrapperPanel check_2
514                        useConstr=V_Value
515                       
516                        if(!CheckFunctionAndCoef(funcStr,coefStr))
517                                DoAlert 0,"The coefficients and function type do not match. Please correct the selections in the popup menus."
518                                break
519                        endif
520                       
521                        FitWrapper(folderStr,funcStr,coefStr,useCursors,useEps,useConstr)
522                       
523                        //      DoUpdate (does not work!)
524                        //?? why do I need to force an update ??
525                        if(!exists("root:"+folderStr+":"+coefStr))
526                                Wave w=$coefStr
527                        else
528                                Wave w=$("root:"+folderStr+":"+coefStr) //smeared coefs in data folder
529                        endif
530                        w[0] += 1e-6
531                        w[0] -= 1e-6
532       
533                        break
534        endswitch
535       
536        return 0
537End
538
539Function CheckFunctionAndCoef(funcStr,coefStr)
540        String funcStr,coefStr
541       
542        SVAR listStr=root:coefKWStr
543        String properCoefStr = StringByKey(funcStr, listStr  ,"=",";",0)
544        if(cmpstr(coefStr,properCoefStr)==0)
545                return(1)               //true, the coef is the correct match
546        endif
547        return(0)                       //false, wrong coef
548End
549
550/////////////////////////////////
551
552// wrapper to do the desired fit
553//
554// folderStr is the data folder for the desired data set
555//
556//
557Function FitWrapper(folderStr,funcStr,coefStr,useCursors,useEps,useConstr)
558        String folderStr,funcStr,coefStr
559        Variable useCursors,useEps,useConstr
560
561        String suffix=getModelSuffix(coefStr)
562       
563        SetDataFolder $("root:"+folderStr)
564        if(!exists(coefStr))
565                // must be unsmeared model, work in the root folder
566                SetDataFolder root:                             
567                if(!exists(coefStr))            //this should be fine if the coef filter is working, but check anyhow
568                        DoAlert 0,"the coefficient and data sets do not match"
569                        return 0
570                endif
571        endif
572               
573        WAVE cw=$(coefStr)     
574        Wave hold=$("Hold_"+suffix)
575        Wave/T lolim=$("LoLim_"+suffix)
576        Wave/T hilim=$("HiLim_"+suffix)
577        Wave eps=$("epsilon_"+suffix)
578       
579// fill a struct instance whether I need one or not
580        String DF="root:"+folderStr+":"
581       
582        Struct ResSmearAAOStruct fs
583        WAVE resW = $(DF+folderStr+"_res")             
584        WAVE fs.resW =  resW
585        WAVE yw=$(DF+folderStr+"_i")
586        WAVE xw=$(DF+folderStr+"_q")
587        WAVE sw=$(DF+folderStr+"_s")
588        Wave fs.coefW = cw
589        Wave fs.yW = yw
590        Wave fs.xW = xw
591       
592        Duplicate/O yw $(DF+"FitYw")
593        WAVE fitYw = $(DF+"FitYw")
594        fitYw = NaN
595       
596        Variable useRes=0
597        if(stringmatch(funcStr, "Smear*"))              // if it's a smeared function, need a struct
598                useRes=1
599        endif
600       
601        // do not construct constraints for any of the coefficients that are being held
602        // -- this will generate an "unknown error" from the curve fitting
603        Make/O/T/N=0 constr
604        if(useConstr)
605                String constraintExpression
606                Variable i, nPnts=DimSize(lolim, 0),nextRow=0
607                for (i=0; i < nPnts; i += 1)
608                        if (strlen(lolim[i]) > 0 && hold[i] == 0)
609                                InsertPoints nextRow, 1, constr
610                                sprintf constraintExpression, "K%d > %s", i, lolim[i]
611                                constr[nextRow] = constraintExpression
612                                nextRow += 1
613                        endif
614                        if (strlen(hilim[i]) > 0 && hold[i] == 0)
615                                InsertPoints nextRow, 1, constr
616                                sprintf constraintExpression, "K%d < %s", i, hilim[i]
617                                constr[nextRow] = constraintExpression
618                                nextRow += 1
619                        endif
620                endfor
621        endif
622
623        //if useCursors, and the data is USANS, need to feed a (reassigned) trimmed matrix to the fit
624        Variable pt1,pt2,newN
625        if(useCursors && (dimsize(resW,1) > 4) )
626                if(pcsr(A) > pcsr(B))
627                        pt1 = pcsr(B)
628                        pt2 = pcsr(A)
629                else
630                        pt1 = pcsr(A)
631                        pt2 = pcsr(B)
632                endif
633                newN = pt2 - pt1 + 1            // +1 includes both cursors in the fit
634                Make/O/D/N=(newN,newN) $(DF+"crsrResW")
635                WAVE crsrResW = $(DF+"crsrResW")
636                crsrResW = resW[p+pt1][q+pt1]
637                //assign to the struct
638                WAVE fs.resW =  crsrResW               
639        endif
640
641// create these variables so that FuncFit will set them on exit
642        Variable/G V_FitError=0                         //0=no err, 1=error,(2^1+2^0)=3=singular matrix
643        Variable/G V_FitQuitReason=0            //0=ok,1=maxiter,2=user stop,3=no chisq decrease
644       
645// don't use the auto-destination with no flag, it doesn't appear to work correctly
646// dispatch the fit
647        do
648                if(useRes && useEps && useCursors && useConstr)         //do it all
649                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw[pcsr(A),pcsr(B)] /X=xw /W=sw /I=1 /E=eps /D=fitYw /C=constr /STRC=fs
650                        break
651                endif
652               
653                if(useRes && useEps && useCursors)              //no constr
654                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw[pcsr(A),pcsr(B)] /X=xw /W=sw /I=1 /E=eps /D=fitYw /STRC=fs
655                        break
656                endif
657               
658                if(useRes && useEps && useConstr)               //no crsr
659                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw /X=xw /W=sw /I=1 /E=eps /D=fitYw /C=constr /STRC=fs
660                        break
661                endif
662               
663                if(useRes && useCursors && useConstr)           //no eps
664                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw[pcsr(A),pcsr(B)] /X=xw /W=sw /I=1 /D=fitYw /C=constr /STRC=fs
665                        break
666                endif
667               
668                if(useRes && useCursors)                //no eps, no constr
669                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw[pcsr(A),pcsr(B)] /X=xw /W=sw /I=1 /D=fitYw /STRC=fs
670                        break
671                endif
672               
673                if(useRes && useEps)            //no crsr, no constr
674//                      Print "timing test for Cylinder_PolyRadius --- the supposedly threaded version ---"
675//                      Variable t0 = stopMStimer(-2)
676                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw /X=xw /W=sw /I=1 /E=eps /D=fitYw /STRC=fs
677//                      t0 = (stopMSTimer(-2) - t0)*1e-6
678//                      Printf  "CylPolyRad fit time using res and eps and /NTHR=0 time = %g seconds\r\r",t0
679                       
680//                      cw[0] = .01
681//                      cw[1] = 20
682//                      cw[2] = 400
683//                      cw[3] = 0.2
684//                      cw[4] = 3e-6
685//                      cw[5] = 0.0
686//                     
687//                      t0 = stopMSTimer(-2)
688//                      FuncFit/H=getHStr(hold) $funcStr cw, yw /X=xw /W=sw /I=1 /E=eps /D=fitYw /STRC=fs
689//                      t0 = (stopMSTimer(-2) - t0)*1e-6
690//                      Printf  "CylPolyRad fit time using res and eps and NO THREADING time = %g seconds\r\r",t0
691                        break
692                endif
693       
694                if(useRes && useConstr)         //no crsr, no eps
695                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw /X=xw /W=sw /I=1 /D=fitYw /C=constr /STRC=fs
696                        break
697                endif
698               
699                if(useRes)              //just res
700                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw /X=xw /W=sw /I=1 /D=fitYw /STRC=fs
701                        break
702                endif
703               
704/////   same as above, but all without useRes (no /STRC flag)
705                if(useEps && useCursors && useConstr)           //do it all
706                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw[pcsr(A),pcsr(B)] /X=xw /W=sw /I=1 /E=eps /D=fitYw /C=constr
707                        break
708                endif
709               
710                if(useEps && useCursors)                //no constr
711                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw[pcsr(A),pcsr(B)] /X=xw /W=sw /I=1 /E=eps /D=fitYw
712                        break
713                endif
714               
715                if(useEps && useConstr)         //no crsr
716                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw /X=xw /W=sw /I=1 /E=eps /D=fitYw /C=constr
717                        break
718                endif
719               
720                if(useCursors && useConstr)             //no eps
721                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw[pcsr(A),pcsr(B)] /X=xw /W=sw /I=1 /D=fitYw /C=constr
722                        break
723                endif
724               
725                if(useCursors)          //no eps, no constr
726                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw[pcsr(A),pcsr(B)] /X=xw /W=sw /I=1 /D=fitYw
727                        break
728                endif
729               
730                if(useEps)              //no crsr, no constr
731                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw /X=xw /W=sw /I=1 /E=eps /D=fitYw
732                        break
733                endif
734       
735                if(useConstr)           //no crsr, no eps
736                        FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw /X=xw /W=sw /I=1 /D=fitYw /C=constr
737                        break
738                endif
739               
740                //just a plain vanilla fit
741                FuncFit/H=getHStr(hold) /NTHR=0 $funcStr cw, yw /X=xw /W=sw /I=1 /D=fitYw
742       
743        while(0)
744       
745        // append the fit
746        // need to manage duplicate copies
747        // Don't plot the full curve if cursors were used (set fitYw to NaN on entry...)
748        String traces=TraceNameList("", ";", 1 )                //"" as first parameter == look on the target graph
749        if(strsearch(traces,"FitYw",0) == -1)
750                AppendToGraph FitYw vs xw
751        else
752                RemoveFromGraph FitYw
753                AppendToGraph FitYw vs xw
754        endif
755        ModifyGraph lsize(FitYw)=2,rgb(FitYw)=(0,0,0)
756       
757        DoUpdate                //force update of table and graph with fitted values (why doesn't this work? - the table still does not update)
758       
759        // report the results (to the panel?)
760        print "V_chisq = ",V_chisq
761        print cw
762        WAVE w_sigma
763        print w_sigma
764        String resultStr=""
765               
766        //now re-write the results
767        sprintf resultStr,"Chi^2 = %g  Sqrt(X^2/N) = %g",V_chisq,sqrt(V_chisq/V_Npnts)
768        resultStr = PadString(resultStr,63,0x20)
769        GroupBox grpBox_2 title=resultStr
770        ControlUpdate/W=WrapperPanel grpBox_2
771        sprintf resultStr,"FitErr = %s : FitQuit = %s",W_ErrorMessage(V_FitError),W_QuitMessage(V_FitQuitReason)
772        resultStr = PadString(resultStr,63,0x20)
773        GroupBox grpBox_3 title=resultStr
774        ControlUpdate/W=WrapperPanel grpBox_3
775       
776        Variable yesSave=0,yesReport=0
777        ControlInfo/W=WrapperPanel check_4
778        yesReport = V_Value
779        ControlInfo/W=WrapperPanel check_5
780        yesSave = V_Value
781       
782       
783        if(yesReport)
784                String parStr=GetWavesDataFolder(cw,1)+ WaveList("*param*"+suffix, "", "TEXT:1," )              //this is *hopefully* one wave
785                String topGraph= WinName(0,1)   //this is the topmost graph
786       
787                DoUpdate                //force an update of the graph before making a copy of it for the report
788
789                W_GenerateReport(funcStr,folderStr,$parStr,cw,yesSave,V_chisq,W_sigma,V_npnts,V_FitError,V_FitQuitReason,V_startRow,V_endRow,topGraph)
790        endif
791       
792        SetDataFolder root:
793        return(0)
794End
795
796// parse something off of a table, or ?
797Function/S getHStr(hold)
798        Wave hold
799       
800        String str=""
801        Variable ii
802        for(ii=0;ii<numpnts(hold);ii+=1)
803                str += num2str(hold[ii])
804        endfor
805
806//      print str
807        if(strsearch(str, "1", 0) == -1)
808                return ("")
809        else
810                return(str)
811        endif
812End
813
814//taken from SRK Auto_Fit, and modified to work better with FitWrapper
815//must have AutoGraph as the name of the graph window (any size)
816// func is the name of the function (for print only)
817//par and coef are the exact names of the waves
818//yesSave==1 will save the file(name=func+time)
819//
820Function W_GenerateReport(func,dataname,param,ans,yesSave,chiSq,sigWave,npts,fitErr,fitQuit,fitStart,fitEnd,topGraph)
821        String func,dataname
822        Wave/T param
823        Wave ans
824        Variable yesSave,chiSq
825        Wave sigWave
826        Variable npts,fitErr,fitQuit,fitStart,fitEnd
827        String topGraph
828       
829        String str,pictStr="P_"
830        String nb="Report"
831               
832        // bring report up
833        DoWindow/F Report
834        if (V_flag == 0)                // Report notebook doesn't exist ?
835                NewNotebook/W=(10,45,550,620)/F=1/N=Report as "Report"
836        endif
837        // delete old stuff
838        Notebook $nb selection={startOfFile, endOfFile}, text="\r", selection={startOfFile, startOfFile}
839       
840        //setup
841        Notebook $nb defaultTab=36, statusWidth=252, pageMargins={72,72,72,72}
842        Notebook $nb showRuler=1, rulerUnits=1, updating={1, 60}
843        Notebook $nb newRuler=Normal, justification=0, margins={0,0,468}, spacing={0,0,0}, tabs={}, rulerDefaults={"Geneva",10,0,(0,0,0)}
844//     
845        // insert title
846        Notebook $nb newRuler=Title, justification=1, rulerDefaults={"Times", 16, 1, (0, 0, 0)}
847        sprintf str, "Fit to %s, %s, %s\r\r", func,Secs2Date(datetime, 0), time()
848        Notebook $nb ruler=Title, text=str
849       
850        // insert fit results
851        Variable num=numpnts(ans),ii=0
852        Notebook $nb ruler=Normal
853        Notebook $nb  margins={18,18,504}, tabs={63 + 3*8192}
854        str = "Data file: " + dataname + "\r\r"
855        Notebook $nb text=str
856        Notebook $nb ruler=Normal
857        Notebook $nb margins={18,18,504}, tabs={144,234,252}
858        do
859                sprintf str, "%s = \t%g\t±\t%g\r", param[ii],ans[ii],sigwave[ii]
860                Notebook $nb text=str
861                ii+=1
862        while(ii<num)
863       
864        //
865        // no "fitted range" for 2D data, so make sure that this exists before using it
866        Wave/Z dataXw = $("root:"+dataname+":"+dataname+"_q")   
867        //
868        Notebook $nb ruler=Normal
869        Notebook $nb  margins={18,18,504}, tabs={63+3*8192}, fStyle=1, textRGB=(65000,0,0)
870       
871        sprintf str,"chisq = %g\r",chisq
872        Notebook $nb textRGB=(65000,0,0),fstyle=1,text=str
873        sprintf str,"Npnts = %g \t\t Sqrt(X^2/N) = %g\r",npts,sqrt(chiSq/npts)
874        Notebook $nb textRGB=(0,0,0),fstyle=0, text=str
875        if(WaveExists(dataXw))
876                sprintf str "Fitted range = [%d,%d] = %g < Q < %g\r",fitStart,fitEnd,dataXw(fitStart),dataXw(fitEnd)
877                Notebook $nb textRGB=(0,0,0),fstyle=0, text=str
878        endif
879        sprintf str,"FitError = %s\t\tFitQuitReason = %s\r",W_ErrorMessage(FitErr),W_QuitMessage(FitQuit)
880        Notebook $nb textRGB=(65000,0,0),fstyle=1,text=str
881        Notebook $nb ruler=Normal
882       
883        // insert graphs
884        if(WaveExists(dataXw))
885                Notebook $nb picture={$topGraph(0, 0, 400, 300), 0, 1}, text="\r"
886        //
887        else            //must be 2D Gizmo
888                Execute "ExportGizmo Clip"
889                LoadPict/Q/O "Clipboard",tmp_Gizmo
890                Notebook $nb picture={tmp_Gizmo(0, 0, 400, 300), 0, 1}, text="\r"
891        endif
892        //Notebook Report picture={Table1, 0, 0}, text="\r"
893       
894        // show the top of the report
895        Notebook $nb  selection= {startOfFile, startOfFile},  findText={"", 1}
896       
897        //save the notebook and the graphic file
898        if(yesSave)
899                String nameStr=CleanupName(func,0)
900                nameStr = nameStr[0,8]  //shorten the name
901                nameStr += "_"+dataname
902                //make sure the name is no more than 31 characters
903                namestr = namestr[0,30]         //if shorter than 31, this will NOT pad to 31 characters
904                Print "file saved as ",nameStr
905                SaveNotebook /O/P=home/S=2 $nb as nameStr
906                //save the graph separately as a PICT file, 2x screen
907                pictStr += nameStr
908                pictStr = pictStr[0,28]         //need a shorter name - why?
909//              DoWindow/F $topGraph
910                // E=-5 is png @screen resolution
911                // E=2 is PICT @2x screen resolution
912///             SavePICT /E=-5/O/P=home /I/W=(0,0,3,3) as pictStr
913                if(WaveExists(dataXw))
914                        SavePICT /E=-5/O/P=home/WIN=$topGraph /W=(0,0,400,300) as pictStr
915                else
916                        Execute "ExportGizmo /P=home as \""+pictStr+"\""
917                        //SavePICT /E=-5/O/P=home/WIN=$topGraph /W=(0,0,400,300) as pictStr
918                endif
919        Endif
920       
921        // ???maybe print the notebook too?
922End
923
924Function/S W_ErrorMessage(code)
925        Variable code
926       
927        switch (code)
928                case 0:
929                        return "No Error"
930                        break
931                case 3: //2^0 + 2^1
932                        return "Singular Matrix"
933                        break
934                case 5:         //(2^0 + 2^2)
935                        return "Out of Memory"
936                        break
937                case 9:         //(2^0 + 2^3)
938                        return "Func= NaN or Inf"
939                        break
940                default:
941                        return "Unknown error code "+num2str(code)
942        endswitch
943end
944
945Function/S W_QuitMessage(code)
946        Variable code
947       
948        switch (code)
949                case 0:
950                        return "No Error"
951                        break
952                case 1:
953                        return "Max iterations - re-run fit"
954                        break
955                case 2:
956                        return "User terminated fit"
957                        break
958                case 3:
959                        return "No decrease in chi-squared"
960                        break
961                default:
962                        return "Unknown Quit code "+num2str(code)
963        endswitch
964end
965
966Function Toggle2DControlsCheckProc(cba) : CheckBoxControl
967        STRUCT WMCheckboxAction &cba
968
969        switch( cba.eventCode )
970                case 2: // mouse up
971                        Variable checked = cba.checked
972                        if(checked)
973                                //print "change the buttons to 2D"
974                                Button button_0,proc=Do2DFitButtonProc,title="Do 2D Fit"
975                                Button button_1,size={120,20},proc=Plot2DFunctionButtonProc,title="Plot 2D Function"
976                                Button button_2,size={100,20},proc=Append2DModelButtonProc,title="Append 2D"
977                                Button button_3,size={100,20},proc=Load2DDataButtonProc,title="Load 2D Data"
978                               
979                                Button button_2D_0,pos={550,60},size={70,20},proc=LogToggle2DButtonProc,title="Log/Lin"
980                                Button button_2D_1,pos={520,37},size={100,20},proc=Plot2DButtonProc,title="Plot 2D Data"
981                               
982                                Button button_2D_0,disable=0            //visible again, and enabled
983                                Button button_2D_1,disable=0
984                        else
985                                //print "unchecked, change them back to 1D"
986                                Button button_0,pos={520,93},size={100,20},proc=DoTheFitButton,title="Do 1D Fit"
987                                Button button_1,pos={280,57},size={120,20},proc=PlotModelFunction,title="Plot 1D Function"
988                                Button button_2,pos={300,93},size={100,20},proc=AppendModelToTarget,title="Append 1D"
989                                Button button_3,pos={300,20},size={100,20},proc=W_LoadDataButtonProc,title="Load 1D Data"
990                               
991                                Button button_2D_0,disable=3    //hide the extra 2D buttons, and disable
992                                Button button_2D_1,disable=3
993                        endif
994                        break
995        endswitch
996
997        return 0
998End
Note: See TracBrowser for help on using the repository browser.