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

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

Changed the search for the parameters_ wave, that occasionally failed if similar suffixes were present - "Peak_Lorentz" and "Lorentz" open at the same time barfed, since it couldn't uniquely identify the parameter wave.

* the parameter wave MUST be named "parameters_suffix" or smear... since it's now searching for "*parameters_"+suffix
(all are currently OK)

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