source: sans/Dev/trunk/NCNR_User_Procedures/SANS/Analysis/Models/Packages/Wrapper_v40.ipf @ 380

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

Changes in response to Lionel:

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