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

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

Bug fix: changed 2D functions to use MultiThread? keyword. Hand-threading previusly worked in Igor 6.12, but gives an index out of range error in Igor 6.2. New version is easier, bug report sent to WM.

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