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

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

Lots of changes to the polarization routines, mostly to incorporate error propagation to the matrix inversion for the polarization correction to the data. Switched the big PolCor? panel to use listboxes to specify files to add together rather than individual popups. Right now 10 files can be added, but this could be expanded to an unlimited number.

Also some minor bug fixes and error handling.

File size: 43.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 useResol=0,isUSANS=0,val
797        if(stringmatch(funcStr, "Smear*"))              // if it's a smeared function, need a struct
798                useResol=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(useResol,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(useResol && useResiduals && useTextBox)              //do it all
925                        FuncFit/H=getHStr(hold) /M=2 /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(useResol && useResiduals)            //res + resid
930                        FuncFit/H=getHStr(hold) /M=2 /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(useResol && useTextBox)              //res + text
936                        FuncFit/H=getHStr(hold) /M=2 /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(useResol)            //res only
941//                      Print "timing test for Cylinder_PolyRadius---"
942//                      Variable t0 = stopMStimer(-2)
943
944                        FuncFit/H=getHStr(hold) /M=2 /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 useResol (no /STRC flag)
965                if(useResiduals && useTextBox)          //resid+ text
966                        FuncFit/H=getHStr(hold) /M=2 /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) /M=2 /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) /M=2 /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) /M=2 /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... but pt1 and pt2 are set and passed!. The V_ variables are more foolproof
1063                // so keep these for the "normal" report
1064                //
1065                if(useGenCurveFit)     
1066                        W_GenerateReport(funcStr,folderStr,$parStr,cw,yesSave,V_chisq,W_sigma,V_npnts,V_FitError,V_FitQuitReason,pt1,pt2,topGraph)
1067                else
1068                        W_GenerateReport(funcStr,folderStr,$parStr,cw,yesSave,V_chisq,W_sigma,V_npnts,V_FitError,V_FitQuitReason,V_startRow,V_endRow,topGraph)
1069                endif
1070        endif
1071       
1072        SetDataFolder root:
1073        return(0)
1074End
1075
1076// parse something off of a table, or ?
1077Function/S getHStr(hold)
1078        Wave hold
1079       
1080        String str=""
1081        Variable ii
1082        for(ii=0;ii<numpnts(hold);ii+=1)
1083                str += num2str(hold[ii])
1084        endfor
1085
1086//      print str
1087        if(strsearch(str, "1", 0) == -1)
1088                return ("")
1089        else
1090                return(str)
1091        endif
1092End
1093
1094//taken from SRK Auto_Fit, and modified to work better with FitWrapper
1095//must have AutoGraph as the name of the graph window (any size)
1096// func is the name of the function (for print only)
1097//par and coef are the exact names of the waves
1098//yesSave==1 will save the file(name=func+time)
1099//
1100Function W_GenerateReport(func,dataname,param,ans,yesSave,chiSq,sigWave,npts,fitErr,fitQuit,fitStart,fitEnd,topGraph)
1101        String func,dataname
1102        Wave/T param
1103        Wave ans
1104        Variable yesSave,chiSq
1105        Wave sigWave
1106        Variable npts,fitErr,fitQuit,fitStart,fitEnd
1107        String topGraph
1108       
1109        String str,pictStr="P_"
1110        String nb="Report"
1111               
1112        // bring report up
1113        DoWindow/F Report
1114        if (V_flag == 0)                // Report notebook doesn't exist ?
1115                NewNotebook/W=(10,45,550,620)/F=1/N=Report as "Report"
1116        endif
1117        // delete old stuff
1118        Notebook $nb selection={startOfFile, endOfFile}, text="\r", selection={startOfFile, startOfFile}
1119       
1120        //setup
1121        Notebook $nb defaultTab=36, statusWidth=252, pageMargins={72,72,72,72}
1122        Notebook $nb showRuler=1, rulerUnits=1, updating={1, 60}
1123        Notebook $nb newRuler=Normal, justification=0, margins={0,0,468}, spacing={0,0,0}, tabs={}, rulerDefaults={"Geneva",10,0,(0,0,0)}
1124//     
1125        // insert title
1126        Notebook $nb newRuler=Title, justification=1, rulerDefaults={"Times", 16, 1, (0, 0, 0)}
1127        sprintf str, "Fit to %s, %s, %s\r\r", func,Secs2Date(datetime, 0), time()
1128        Notebook $nb ruler=Title, text=str
1129       
1130        // insert fit results
1131        Variable num=numpnts(ans),ii=0
1132        Notebook $nb ruler=Normal
1133        Notebook $nb  margins={18,18,504}, tabs={63 + 3*8192}
1134        str = "Data file: " + dataname + "\r\r"
1135        Notebook $nb text=str
1136        Notebook $nb ruler=Normal
1137        Notebook $nb margins={18,18,504}, tabs={144,234,252}
1138        do
1139                sprintf str, "%s = \t%g\t±\t%g\r", param[ii],ans[ii],sigwave[ii]
1140                Notebook $nb text=str
1141                ii+=1
1142        while(ii<num)
1143       
1144        //
1145        // no "fitted range" for 2D data, so make sure that this exists before using it
1146        Wave/Z dataXw = $("root:"+dataname+":"+dataname+"_q")   
1147        //
1148        Notebook $nb ruler=Normal
1149        Notebook $nb  margins={18,18,504}, tabs={63+3*8192}, fStyle=1, textRGB=(65000,0,0)
1150       
1151        sprintf str,"chisq = %g\r",chisq
1152        Notebook $nb textRGB=(65000,0,0),fstyle=1,text=str
1153        sprintf str,"Npnts = %g \t\t Sqrt(X^2/N) = %g\r",npts,sqrt(chiSq/npts)
1154        Notebook $nb textRGB=(0,0,0),fstyle=0, text=str
1155        if(WaveExists(dataXw))
1156                sprintf str "Fitted range = [%d,%d] = %g < Q < %g\r",fitStart,fitEnd,dataXw(fitStart),dataXw(fitEnd)
1157                Notebook $nb textRGB=(0,0,0),fstyle=0, text=str
1158        endif
1159        sprintf str,"FitError = %s\t\tFitQuitReason = %s\r",W_ErrorMessage(FitErr),W_QuitMessage(FitQuit)
1160        Notebook $nb textRGB=(65000,0,0),fstyle=1,text=str
1161        Notebook $nb ruler=Normal
1162       
1163        // insert graphs
1164        if(WaveExists(dataXw))
1165//              Notebook $nb picture={$topGraph(0, 0, 400, 300), -5, 1}, text="\r"
1166                Notebook $nb scaling={50, 50}, picture={$topGraph(0, 0, 800, 600), -5, 1}, text="\r"
1167        //
1168        else            //must be 2D Gizmo
1169                Execute "ExportGizmo Clip"                      //this ALWAYS is a PICT or BMP. Gizmo windows are different...
1170                LoadPict/Q/O "Clipboard",tmp_Gizmo
1171                Notebook $nb picture={tmp_Gizmo(0, 0, 800, 600), 0, 1}, text="\r"
1172        endif
1173       
1174        // show the top of the report
1175        Notebook $nb  selection= {startOfFile, startOfFile},  findText={"", 1}
1176       
1177        //save the notebook and the graphic file
1178        if(yesSave)
1179                String nameStr=CleanupName(func,0)
1180                nameStr += "_"+dataname
1181                nameStr = ReplaceString("Smeared",nameStr,"Sm_")                //if Smeared function, shorten the name
1182                //make sure the name is no more than 31 characters
1183                namestr = namestr[0,30]         //if shorter than 31, this will NOT pad to 31 characters
1184                Print "file saved as ",nameStr
1185                SaveNotebook /O/P=home/S=2 $nb as nameStr
1186                //save the graph separately as a PNG file, 2x screen
1187                pictStr += nameStr
1188                pictStr = pictStr[0,28]         //need a shorter name - why?
1189//              DoWindow/F $topGraph
1190                // E=-5 is png @screen resolution
1191                // E=2 is PICT @2x screen resolution
1192///             SavePICT /E=-5/O/P=home /I/W=(0,0,3,3) as pictStr
1193                if(WaveExists(dataXw))
1194                        SavePICT /E=-5/O/P=home/WIN=$topGraph /W=(0,0,800,600) as pictStr
1195                else
1196                        Execute "ExportGizmo /P=home as \""+pictStr+"\""                //this won't be of very high quality
1197                        //SavePICT /E=-5/O/P=home/WIN=$topGraph /W=(0,0,400,300) as pictStr
1198                endif
1199        Endif
1200       
1201        // ???maybe print the notebook too?
1202End
1203
1204Function/S W_ErrorMessage(code)
1205        Variable code
1206       
1207        switch (code)
1208                case 0:
1209                        return "No Error"
1210                        break
1211                case 3: //2^0 + 2^1
1212                        return "Singular Matrix"
1213                        break
1214                case 5:         //(2^0 + 2^2)
1215                        return "Out of Memory"
1216                        break
1217                case 9:         //(2^0 + 2^3)
1218                        return "Func= NaN or Inf"
1219                        break
1220                default:
1221                        return "Unknown error code "+num2str(code)
1222        endswitch
1223end
1224
1225Function/S W_QuitMessage(code)
1226        Variable code
1227       
1228        switch (code)
1229                case 0:
1230                        return "No Error"
1231                        break
1232                case 1:
1233                        return "Max iterations - re-run fit"
1234                        break
1235                case 2:
1236                        return "User terminated fit"
1237                        break
1238                case 3:
1239                        return "No decrease in chi-squared"
1240                        break
1241                default:
1242                        return "Unknown Quit code "+num2str(code)
1243        endswitch
1244end
1245
1246Function UseInfoTextBoxCheckProc(cba) : CheckBoxControl
1247        STRUCT WMCheckboxAction &cba
1248
1249        switch( cba.eventCode )
1250                case 2: // mouse up
1251                        Variable checked = cba.checked
1252                        if(checked)
1253                                //print "checked, use textBox in the next fit"
1254                        else
1255                                //print "unchecked, ask to remove TextBox from the graph"
1256                                ControlInfo/W=WrapperPanel popup_0
1257                                RemoveTextBox(S_value)
1258                        endif
1259                        break
1260        endswitch
1261
1262        return 0
1263End
1264
1265//does not report an error if the text box is not there
1266// -- so I'll just be lazy and not check to see if it's there
1267//
1268Function RemoveTextBox(folderStr)
1269        String folderStr
1270       
1271        DoAlert 1,"Remove the TextBox from the graph?"
1272        if(V_flag == 1)
1273                String str = "CF_"+folderStr+"_i"
1274                TextBox/K/N=$str
1275        endif
1276        return(0)
1277End
1278
1279Function UseResidualsCheckProc(cba) : CheckBoxControl
1280        STRUCT WMCheckboxAction &cba
1281
1282        switch( cba.eventCode )
1283                case 2: // mouse up
1284                        Variable checked = cba.checked
1285                        if(checked)
1286                                //print "checked, use them in the next fit"
1287                        else
1288                                //print "unchecked, ask to remove residuals from the graph"
1289                                ControlInfo/W=WrapperPanel popup_0
1290                                RemoveResiduals(S_value)
1291                        endif
1292                        break
1293        endswitch
1294
1295        return 0
1296End
1297
1298// the default name from the /R flag is "Res_" + yWaveName
1299//
1300// better to find the wave that starts with "Res_" and remove that one in case the
1301// wave names get too long
1302//
1303// the difficulty now is that the residual wave ends up in root: and not with the data....
1304// -- not really a problem, but adds to clutter
1305Function RemoveResiduals(folderStr)
1306        String folderStr
1307       
1308        String list="",topWin=""
1309        Variable num,ii
1310        String str
1311
1312        DoAlert 1,"Remove the residuals from the graph?"
1313        if(V_flag == 1)
1314//              String topGraph= WinName(0,1)   //this is the topmost graph
1315                list=TraceNameList("", ";", 1 )         //"" as first parameter == look on the target graph
1316                num=ItemsInList(list)
1317               
1318                for(ii=0;ii<num;ii+=1)
1319                        str = StringFromList(ii, list ,";")
1320                        if(strsearch(str, "Res_", 0) != -1)
1321                                RemoveFromGraph $str
1322                        endif
1323                endfor
1324       
1325                SetDataFolder root:
1326        endif
1327       
1328        return(0)
1329End
1330
1331Function Toggle2DControlsCheckProc(cba) : CheckBoxControl
1332        STRUCT WMCheckboxAction &cba
1333
1334        switch( cba.eventCode )
1335                case 2: // mouse up
1336                        Variable checked = cba.checked
1337                        if(checked)
1338                                //print "change the buttons to 2D"
1339                                Button button_0,proc=Do2DFitButtonProc,title="Do 2D Fit"
1340                                Button button_1,size={120,20},proc=Plot2DFunctionButtonProc,title="Plot 2D Function"
1341                                Button button_2,size={100,20},proc=Append2DModelButtonProc,title="Append 2D"
1342                                Button button_3,size={100,20},proc=Load2DDataButtonProc,title="Load 2D Data"
1343                               
1344                                Button button_2D_0,pos={550,60},size={70,20},proc=LogToggle2DButtonProc,title="Log/Lin"
1345                                Button button_2D_1,pos={520,37},size={100,20},proc=Plot2DButtonProc,title="Plot 2D Data"
1346                               
1347                                Button button_2D_0,disable=0            //visible again, and enabled
1348                                Button button_2D_1,disable=0
1349                               
1350                                CheckBox check_6,disable=1                      //info box and residual check, remove these from view
1351                                CheckBox check_7,disable=1
1352                        else
1353                                //print "unchecked, change them back to 1D"
1354                                Button button_0,pos={520,93},size={100,20},proc=DoTheFitButton,title="Do 1D Fit"
1355                                Button button_1,pos={280,57},size={120,20},proc=PlotModelFunction,title="Plot 1D Function"
1356                                Button button_2,pos={300,93},size={100,20},proc=AppendModelToTarget,title="Append 1D"
1357                                Button button_3,pos={300,20},size={100,20},proc=W_LoadDataButtonProc,title="Load 1D Data"
1358                               
1359                                Button button_2D_0,disable=3    //hide the extra 2D buttons, and disable
1360                                Button button_2D_1,disable=3
1361                               
1362                                CheckBox check_6,disable=0                      //info box and residual check, bring them back
1363                                CheckBox check_7,disable=0
1364                        endif
1365                        break
1366        endswitch
1367
1368        return 0
1369End
1370
1371// function to either add or remove the cursors from the topmost graph, as needed
1372
1373Function UseCursorsWrapperProc(cba) : CheckBoxControl
1374        STRUCT WMCheckboxAction &cba
1375
1376
1377        switch( cba.eventCode )
1378                case 2: // mouse up
1379               
1380                        // check to make sure there really is a "topmost" graph         
1381                        String topGraph= WinName(0,1)   //this is the topmost graph
1382                        if(cmpstr(topGraph,"")==0)      //no graphs, uncheck and exit
1383                                CheckBox check_0,value=0
1384                                return(0)
1385                        endif
1386                       
1387                        //if in 2D mode, just exit
1388                        ControlInfo/W=WrapperPanel check_3
1389                        if(V_Value == 1)
1390                                return (0)
1391                        endif
1392                               
1393                        String ciStr = CsrInfo(A , topGraph)
1394                       
1395                        ControlInfo/W=wrapperpanel popup_0
1396                        String folderStr=S_Value
1397                        String traceList = TraceNameList(topGraph, ";", 1 )             
1398               
1399                        Variable checked = cba.checked
1400                       
1401                        if(checked)
1402                                //print "add the cursors to the topmost graph, if the data set is there, or move them"
1403                                if(strlen(ciStr)==0 && strsearch(traceList, folderStr, 0) != -1 )               //no cursors && data is there
1404                                        ShowInfo
1405                                        Wave yw=$("root:"+folderStr+":"+folderStr+"_i")
1406                                        Cursor/P/W=$topGraph A, $(folderStr+"_i"),0
1407                                        Cursor/P/W=$topGraph/A=0 B, $(folderStr+"_i"),numpnts(yw)-1                     //deactivate the one at the high Q end
1408                                        DoUpdate
1409                                elseif (strlen(ciStr)!=0 && strsearch(traceList, folderStr, 0) != -1 ) //cursors present, but on wrong data
1410                                        Wave yw=$("root:"+folderStr+":"+folderStr+"_i")
1411                                        Cursor/P/W=$topGraph A, $(folderStr+"_i"),0                                                             //move the cursors
1412                                        Cursor/P/W=$topGraph/A=0 B, $(folderStr+"_i"),numpnts(yw)-1
1413                                        DoUpdate
1414                                endif
1415                               
1416                                AreCursorsCorrect(folderStr)
1417                        else
1418                                //print "unchecked, remove the cursors"
1419                                // go back to the full matrix for the resolution calculation (not if SANS data...)
1420                                if(waveExists($("root:"+folderStr+":weights_save")))
1421                                        Duplicate/O $("root:"+folderStr+":weights_save"), $("root:"+folderStr+":"+folderStr+"_res"),$("root:"+folderStr+":"+folderStr+"_rest")
1422                                endif
1423
1424                                HideInfo/W=$topGraph
1425                                Cursor/K A
1426                                Cursor/K B
1427                        endif
1428                        break
1429        endswitch
1430
1431        return 0
1432End
1433
1434// returns 1 if the specified data is on the top graph && has cursors on it
1435// returns 0 and unchecks the box if anything is wrong
1436//
1437// only call this function if the cursor box is checked, to uncheck it as needed
1438// if the box is unchecked, leave it be.
1439//
1440Function AreCursorsCorrect(folderStr)
1441        String folderStr
1442       
1443        String topGraph= WinName(0,1)   //this is the topmost graph
1444        if(cmpstr(topGraph,"")==0)      //no graphs, uncheck and exit
1445                CheckBox check_0,win=wrapperpanel,value=0
1446                return(0)
1447        endif
1448               
1449        String traceAisOn = CsrWave(A , "", 0)
1450        if(     strsearch(traceAisOn, folderStr, 0) == -1)              //data and cursors don't match
1451                CheckBox check_0,win=wrapperpanel,value=0
1452                HideInfo
1453                Cursor/K A
1454                Cursor/K B
1455                return(0)
1456        endif
1457       
1458        return(1)
1459End
1460
1461// displays the covariance matrix for the current data set in the popup
1462// AND whatever was the last fit for that data set. it may not necessarily
1463// be the displayed function...
1464Function DisplayCovarianceMatrix()
1465
1466        ControlInfo/W=wrapperpanel popup_0
1467        String folderStr=S_Value
1468
1469        ControlInfo/W=WrapperPanel popup_1
1470        String funcStr=S_Value
1471                       
1472        if(Stringmatch(funcStr,"Smear*"))               //simple test for smeared function
1473                if(DataFolderExists("root:"+folderStr))
1474                        SetDataFolder $("root:"+folderStr)
1475                else
1476                        SetDataFolder root:
1477                endif
1478        else
1479                SetDataFolder root:
1480        endif
1481       
1482        Wave M_Covar=M_Covar
1483        Duplicate/O M_Covar, CorMat      // You can use any name instead of CorMat
1484        CorMat = M_Covar[p][q]/sqrt(M_Covar[p][p]*M_Covar[q][q])
1485        Edit CorMat
1486       
1487        SetDataFolder root:
1488       
1489        return(0)
1490End
Note: See TracBrowser for help on using the repository browser.