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

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

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

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

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