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

Last change on this file since 728 was 728, checked in by srkline, 12 years ago

Fixed typo in the parameter description in CoreShellCylinder?

W_Sigma is now appended to the table in the wrapper panel when a fit is done.
It is cleared whenever functions or data are changed.

The naming of reports is changed to help make the names more descriptive and unique.

DataSetHandling? - -simple checkbox on the graph to change to a linear display
that highlights the high Q - to be sure that data oscillates around zero
after background subtraction (this doesn't have to stay)

Added a crude batch file converter to take the 5-column grasp data (read in as
if it was old-school desmeared USANS data) and write it back out in our 6-column
ASCII format. Did this for Andrea.

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