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

Last change on this file since 1001 was 1001, checked in by srkline, 6 years ago

A number of simple fixes to make the macros compatible with Igor 7, and in some places back-compatible with Igor 6. There were only a few instances where the IgorVersion? was checked, so it does not caues a huge disruption.

File size: 61.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// this is the flag for the relative error = W_sigma/coef that will
7// trip the bold/red color of W_sigma in the table.
8//
9Constant kRelErrorTolerance=0.5
10
11//Macro OpenWrapperPanel()
12//      Init_WrapperPanel()
13//End
14
15Function Init_WrapperPanel()
16
17        if(itemsinlist(WinList("SA_includes_v400.ipf", ";","INCLUDE:6"),";") != 0)
18                //must be opening a v4.00 or earlier template
19                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"
20        endif
21       
22        //make sure that folders exist - this is the first initialization to be called
23        NewDataFolder/O root:Packages
24        NewDataFolder/O root:Packages:NIST
25
26        //Create useful globals
27        Variable/G root:Packages:NIST:SANS_ANA_VERSION=4.10
28        String/G root:Packages:NIST:SANS_ANA_EXTENSION="_v40"
29        //Set this variable to 1 to force use of trapezoidal integration routine for USANS smearing
30        Variable/G root:Packages:NIST:USANSUseTrap = 0
31        Variable/G root:Packages:NIST:USANS_dQv = 0.117
32        Variable/G root:Packages:NIST:gUseGenCurveFit = 0                       //set to 1 to use genetic optimization
33                       
34        //Ugly. Put this here to make sure things don't break
35        String/G root:Packages:NIST:gXMLLoader_Title
36       
37       
38        //initializes preferences. this includes XML y/n, and SANS Reduction items.
39        // if they already exist, they won't be overwritten
40        Execute "Initialize_Preferences()"             
41       
42        DoWindow/F WrapperPanel
43        if(V_flag==0)
44                if(exists("root:Packages:NIST:coefKWStr")==0)
45                        String/G root:Packages:NIST:coefKWStr=""
46                endif
47                if(exists("root:Packages:NIST:suffixKWStr")==0)
48                        String/G root:Packages:NIST:suffixKWStr=""
49                endif
50                if(exists("root:Packages:NIST:paramKWStr")==0)
51                        String/G root:Packages:NIST:paramKWStr=""
52                endif
53                Execute "WrapperPanel()"
54        endif
55End
56
57////////
58//
59// if model is Smeared, search the DF for coefficients
60// if new DF chosen, need to reset
61// if new model function, need to reset table
62//
63// create hold_mod (0/1), constr_low_mod, constr_hi_mod
64// in either DF (smeared) or in root: (normal)
65// and put these in the table as needed
66//
67Window WrapperPanel()
68        PauseUpdate; Silent 1           // building window...
69        NewPanel /W=(459,44,1113,499)/N=wrapperPanel/K=1 as "Curve Fit Setup"
70        ModifyPanel fixedSize=1
71       
72        GroupBox grpBox_0,pos={18,11},size={390,113}
73        GroupBox grpBox_1,pos={426,10},size={207,113}
74        GroupBox grpBox_2 title="No Fit",pos={10,130},size={0,0},frame=1,fSize=10,fstyle=1,fColor=(39321,1,1)
75        GroupBox grpBox_3 title="",pos={10,150},size={0,0},frame=1,fSize=10,fstyle=1,fColor=(39321,1,1)
76
77        Button button_1,pos={280,57},size={120,20},proc=PlotModelFunction,title="Plot 1D Function"
78        Button button_2,pos={300,93},size={100,20},proc=AppendModelToTarget,title="Append 1D"
79        Button button_3,pos={300,20},size={100,20},proc=W_LoadDataButtonProc,title="Load 1D Data"
80        PopupMenu popup_0,pos={30,21},size={218,20},title="Data Set",proc=DataSet_PopMenuProc
81        PopupMenu popup_0,mode=1,value= #"W_DataSetPopupList()"
82        PopupMenu popup_1,pos={30,57},size={136,20},title="Function"
83        PopupMenu popup_1,mode=1,value= #"W_FunctionPopupList()",proc=Function_PopMenuProc
84        PopupMenu popup_2,pos={30,93},size={123,20},title="Coefficients"
85        PopupMenu popup_2,mode=1,value= #"W_CoefPopupList()",proc=Coef_PopMenuProc
86        CheckBox check_0,pos={430,19},size={79,14},title="Use Cursors?",value= 0
87        CheckBox check_0,proc=UseCursorsWrapperProc
88        CheckBox check_1,pos={430,42},size={74,14},title="Use Epsilon?",value= 0
89        CheckBox check_2,pos={430,65},size={95,14},title="Use Constraints?",value= 0
90        CheckBox check_3,pos={530,18},size={72,14},title="2D Functions?",value= 0
91        CheckBox check_3 proc=Toggle2DControlsCheckProc
92        CheckBox check_4,pos={430,85},size={72,14},title="Report?",value= 0
93        CheckBox check_5,pos={444,103},size={72,14},title="Save it?",value= 0
94        CheckBox check_6,pos={530,38},size={72,14},title="Use Residuals?",value= 0
95        CheckBox check_6,proc=UseResidualsCheckProc
96        CheckBox check_7,pos={530,57},size={72,14},title="Info Box?",value= 0
97        CheckBox check_7,proc=UseInfoTextBoxCheckProc
98        CheckBox check_8, pos={530,75}, size={72,14}, title="Rescale Axis?", value=0
99        CheckBox check_8,proc=UseRescaleAxisCheckProc
100        //change draw order to put button over text of checkbox
101        Button button_0,pos={520,93},size={100,20},proc=DoTheFitButton,title="Do 1D Fit"
102        Button button_4,pos={520,126},size={100,20},proc=FeedbackButtonProc,title="Feedback"
103        Button button_5,pos={520,150},size={100,20},proc=FitHelpButtonProc,title="Help"
104
105        Edit/W=(20,174,634,435)/HOST=# 
106        ModifyTable width(Point)=0
107        RenameWindow #,T0
108        SetActiveSubwindow ##
109EndMacro
110
111//open the Help file for the Fit Manager
112Function FitHelpButtonProc(ba) : ButtonControl
113        STRUCT WMButtonAction &ba
114
115        switch( ba.eventCode )
116                case 2: // mouse up
117                        // click code here
118                        DisplayHelpTopic/Z/K=1 "Fit Manager"
119                        if(V_flag !=0)
120                                DoAlert 0,"The Fit Manager Help file could not be found"
121                        endif
122                        break
123        endswitch
124
125        return 0
126End
127
128
129//open the trac page for feedback
130Function FeedbackButtonProc(ba) : ButtonControl
131        STRUCT WMButtonAction &ba
132
133        switch( ba.eventCode )
134                case 2: // mouse up
135                        // click code here
136                        OpenTracTicketPage()
137                        break
138        endswitch
139
140        return 0
141End
142
143
144//obvious use, now finds the most recent data loaded, finds the folder, and pops the menu with that selection...
145//
146Function W_LoadDataButtonProc(ba) : ButtonControl
147        STRUCT WMButtonAction &ba
148
149        switch( ba.eventCode )
150                case 2: // mouse up
151                        // click code here
152                        String  topGraph= WinName(0,1)
153                        if(strlen(topGraph) != 0)
154                                DoWindow/F $topGraph                    //so that the panel is not on top
155                        endif
156                        Execute "A_LoadOneDData()"
157                       
158                        ControlUpdate/W=WrapperPanel popup_0
159                        //instead of a simple controlUpdate, better to pop the menu to make sure that the other menus follow
160                        // convoluted method to find the right item and pop the menu.
161
162                        // data is plotted, so get the "new" top graph
163                        topGraph= WinName(0,1)  //this is the topmost graph, and should exist, but...
164                        if(cmpstr(topGraph,"")==0)
165                                return(0)
166                        endif
167                        String list,folderStr
168                        Variable num
169                        list = TraceNameList(topGraph,";",1)            //want the last item in the list
170                        num= ItemsInList(list)
171                        FolderStr = StringFromList(num-1,list,";")
172                        folderStr = folderStr[0,strlen(folderStr)-3]            //remove the "_i" that the loader enforced
173                        list = W_DataSetPopupList()
174                        num=WhichListItem(folderStr,list,";",0,0)
175                        if(num != -1)
176                                PopupMenu popup_0,mode=num+1,win=WrapperPanel
177                                ControlUpdate/W=WrapperPanel popup_0
178                               
179                                // fake mouse up to pop the menu
180                                Struct WMPopupAction ps
181                                ps.eventCode = 2                //fake mouse up
182                                DataSet_PopMenuProc(ps)
183                        endif
184                        break
185        endswitch
186       
187        return 0
188End
189
190
191// is there a simpler way to do this? I don't think so.
192Function/S W_DataSetPopupList()
193
194        String str=GetAList(4)
195
196        if(strlen(str)==0)
197                str = "No data loaded"
198        endif
199        str = SortList(str)
200       
201        return(str)
202End
203
204
205// show the available models
206// not the f*(cw,xw) point calculations
207// not the *X(cw,xw) XOPS
208//
209// KIND:10 should show only user-defined curve fitting functions
210// - not XOPs
211// - not other user-defined functions
212Function/S W_FunctionPopupList()
213        String list,tmp
214        //get every user defined curve fit function, remove everything the user doesn't need to see...
215        list = User_FunctionPopupList()         
216
217        if(strlen(list)==0)
218                list = "No functions plotted"
219        endif
220       
221        list = SortList(list)
222        return(list)
223End
224
225
226// show all the appropriate coefficient waves
227//
228// also need to search the folder listed in "data set" popup
229// for smeared coefs
230//
231// - or - restrict the coefficient list based on the model function
232// - new way, filter the possible values based on the data folder and function
233Function/S W_CoefPopupList()
234
235        String notPlotted="Please plot the function"
236        ControlInfo/W=wrapperpanel popup_1
237        String funcStr=S_Value
238        String coefStr=getFunctionCoef(funcStr)
239       
240        if(cmpstr(coefStr,"")==0)               //no correspondence in the KW string
241                return(notPlotted)
242        endif
243       
244       
245        //found a coefficient wave - only two places to look
246        // is it in the root folder?
247        if(exists("root:"+coefStr) != 0)
248                return(coefStr)
249        endif
250       
251        // is it in the data folder?
252        ControlInfo/W=wrapperpanel popup_0
253        String folderStr=S_Value
254        if(exists("root:"+folderStr+":"+coefStr) != 0)
255                return(coefStr)
256        endif
257
258        return(notPlotted)
259End
260
261// show all the appropriate coefficient waves
262//
263// also need to search the folder listed in "data set" popup
264// for smeared coefs
265//
266// - or - restrict the coefficient list based on the model function
267//
268// --old way
269//Function/S W_CoefPopupList()
270//      String list
271//      setDataFolder root:
272//      list = WaveList("coef*",";","")
273//     
274//      ControlInfo/W=wrapperpanel popup_0
275//      if(V_Value != 0)                //0== no items in menu
276//              if(DataFolderExists("root:"+S_Value))
277//                      SetDataFolder $("root:"+S_Value)
278//                      list += WaveList("*coef*",";","")
279//              endif
280//      endif
281//     
282//      // tmp coefficients that aren't being cleaned up from somewhere...
283//      list = RemoveFromList("temp_coef_1;temp_coef_2;", list  ,";")
284//
285//      if(strlen(list)==0)
286//              list = "No functions plotted"
287//      endif
288//      list = SortList(list)
289//     
290////    Print itemsinlist(list,";")
291//     
292//      setDataFolder root:
293//      return(list)
294//End
295
296// if the coefficients are changed, then update the table
297//
298//update the table
299// may be easier to just kill the subwindow (table) and create a new one
300// need to set/reset all of the waves in the table
301//
302// !! only respond to mouse up
303//
304Function Coef_PopMenuProc(pa) : PopupMenuControl
305        STRUCT WMPopupAction &pa
306
307        switch( pa.eventCode )
308                case 2: // mouse up
309                        Variable popNum = pa.popNum
310                        String popStr = pa.popStr
311                        ControlInfo/W=WrapperPanel popup_1
312                        String funcStr=S_Value
313                        String suffix = getModelSuffix(funcStr)
314                        ControlInfo/W=WrapperPanel popup_0
315                        String folderStr=S_Value
316                       
317                        if(cmpstr(popStr,"Please plot the function")==0)
318//                              Print "function not plotted"
319                                return(0)
320                        endif
321
322// this if/else/endif should not ever return an error alert     
323// it should simply set the data folder properly       
324                        if(DataFolderExists("root:"+folderStr))
325                                SetDataFolder $("root:"+folderStr)
326                                if(!exists(popStr))
327                                        // must be unsmeared model, work in the root folder
328                                        SetDataFolder root:                             
329                                        if(!exists(popStr))             //this should be fine if the coef filter is working, but check anyhow
330                                                DoAlert 0,"the coefficient and data sets do not match (1)"
331                                                return 0
332                                        endif
333                                endif
334                        else
335                                // must be unsmeared model, work in the root folder
336                                SetDataFolder root:     
337                                if(!exists(popStr))             //this should be fine if the coef filter is working, but check anyhow
338                                        DoAlert 0,"the coefficient and data sets do not match (2)"
339                                        return 0
340                                endif
341                        endif
342                       
343                        // farm the work out to another function?
344                        Variable num=numpnts($popStr)
345                        // make the necessary waves if they don't exist already
346                        if(exists("Hold_"+suffix) == 0)
347                                Make/O/D/N=(num) $("epsilon_"+suffix),$("Hold_"+suffix)
348                                Make/O/T/N=(num) $("LoLim_"+suffix),$("HiLim_"+suffix)
349                                Wave eps = $("epsilon_"+suffix)
350                                Wave coef=$popStr
351                                if(eps[0] == 0)         //if eps already if filled, don't change it
352                                        eps = abs(coef*1e-4) + 1e-10                    //default eps is proportional to the coefficients
353                                endif
354                        endif
355                        // default epsilon values, sometimes needed for the fit
356                       
357                        WAVE/T LoLim = $("LoLim_"+suffix)
358                        WAVE/T HiLim = $("HiLim_"+suffix)
359                       
360                        // clear the table (a subwindow)
361                        DoWindow/F WrapperPanel                         // ?? had to add this in during all of the cursor meddling...
362                        KillWindow wrapperPanel#T0
363                        Edit/W=(20,174,634,435)/HOST=wrapperPanel
364                        RenameWindow #,T0
365                        // get them onto the table
366                        // how do I get the parameter name?
367                        String param = getFunctionParams(funcStr)
368                        AppendtoTable/W=wrapperPanel#T0 $param,$(popStr)
369                        AppendToTable/W=wrapperPanel#T0 $("Hold_"+suffix),$("LoLim_"+suffix),$("HiLim_"+suffix),$("epsilon_"+suffix)
370                        ModifyTable/W=wrapperPanel#T0 width(Point)=0
371                       
372                        SetDataFolder root:
373                        break
374        endswitch
375
376        return 0
377End
378
379// if the Function is changed, then update the coef popup (if possible) and then the table (if possible)
380//
381// !! only respond to mouse up
382//
383Function Function_PopMenuProc(pa) : PopupMenuControl
384        STRUCT WMPopupAction &pa
385
386        switch( pa.eventCode )
387                case 2: // mouse up
388                        Variable popNum = pa.popNum
389                        String funcStr = pa.popStr
390                        String coefStr = W_CoefPopupList()
391                       
392//                      Print "coefStr = ",coefStr
393                       
394                        ControlInfo/W=WrapperPanel popup_0
395                        String folderStr=S_Value
396                       
397                        String listStr = W_CoefPopupList()
398                        Variable num=WhichListItem(coefStr, listStr, ";")
399                        String str=StringFromList(num, listStr  ,";")
400//                      print "str = ",str
401                        //set the item in the coef popup, and pop it
402                        PopupMenu popup_2 win=WrapperPanel,mode=(num+1)
403                       
404                        Struct WMPopupAction ps
405                        ps.eventCode = 2                //fake mouse up
406                        ps.popStr = str
407                        Coef_PopMenuProc(ps)
408                       
409                        SetDataFolder root:
410                        break
411        endswitch
412
413        return 0
414End
415
416// if the Data Set is changed, then update the function (if possible)
417// and the coef popup (if possible) and then the table (if possible)
418//
419// !! only respond to mouse up here, and simply send a fake mouse up
420// to the function pop, which will do what it can do
421//
422Function DataSet_PopMenuProc(pa) : PopupMenuControl
423        STRUCT WMPopupAction &pa
424       
425        switch( pa.eventCode )
426                case 2: // mouse up
427                        // make sure that the cursors are on/off appropriately
428                        // let the cursors checkbox decide what to do, sending the current state
429                        ControlInfo/W=WrapperPanel check_0
430                        STRUCT WMCheckboxAction cba
431                        cba.eventCode = 2
432                        cba.checked = V_Value
433                        UseCursorsWrapperProc(cba)
434                                       
435                        // then cascade the function/coefficient popups
436                        Struct WMPopupAction ps
437                        ps.eventCode = 2                //fake mouse up
438                        Function_PopMenuProc(ps)
439                       
440                        SetDataFolder root:
441                        break
442        endswitch
443
444        return 0
445End
446
447
448// - this is based on stringent "PlotNNN" naming requirements
449//
450//  ???
451// - how to kill the generated table and graph, that are not needed now
452//
453Function PlotModelFunction(ba) : ButtonControl
454        STRUCT WMButtonAction &ba
455
456        String folderStr,funcStr,coefStr,cmdStr=""
457        Variable useCursors,useEps,useConstr
458       
459        Variable killWhat=0             //kill nothing as default
460       
461        switch( ba.eventCode )
462                case 2: // mouse up
463                        ControlInfo/W=WrapperPanel popup_0
464                        folderStr=S_Value
465                       
466                        ControlInfo/W=WrapperPanel popup_1
467                        funcStr=S_Value
468                       
469                        // maybe nothing has been loaded yet...
470                        if(cmpstr(funcStr,"No functions plotted") == 0)
471                                break
472                        endif
473                       
474                        // check for smeared or smeared function
475                        if(stringmatch(funcStr, "Smear*" )==1)
476                                //it's a smeared model
477                                // check for the special case of RPA that has an extra parameter
478                                if(strsearch(funcStr, "RPAForm", 0 ,0) == -1)
479                                        sprintf cmdStr, "Plot%s(\"%s\")",funcStr,folderStr              //not RPA
480                                else
481                                        sprintf cmdStr, "Plot%s(\"%s\",)",funcStr,folderStr             //yes RPA, leave a comma for input
482                                endif
483                                killWhat = 1
484                        else
485                                // it's not,    don't kill the graph, just the table           
486                                sprintf cmdStr, "Plot%s()",funcStr
487                                killWhat = 2
488                        endif
489                       
490                        //Print cmdStr
491                        Execute cmdStr
492                       
493                        //pop the function menu to set the proper coefficients
494                        DoWindow/F WrapperPanel
495                        STRUCT WMPopupAction pa
496                        pa.popStr = funcStr
497                        pa.eventcode = 2
498                        Function_PopMenuProc(pa)
499       
500                        KillTopGraphAndTable(killWhat)          // crude
501       
502                        break
503        endswitch
504       
505        return 0
506End
507
508// passing 0 kills nothing
509// passing 1 kills the top graph and table
510// passing 2 kills the top table only
511//
512Function KillTopGraphAndTable(killwhat)
513        Variable killWhat
514       
515        String topGraph= WinName(0,1)   //this is the topmost graph     
516        String topTable= WinName(0,2)   //this is the topmost table
517
518        if(killWhat == 0)
519                return(0)
520        endif
521       
522        if(killWhat == 1)
523                KillWindow $topGraph
524                KillWindow $topTable
525        endif
526       
527        if(killWhat == 2)
528                KillWindow $topTable
529        endif
530       
531        return(0)
532End
533
534// How to bypass the step of plot and append?
535//
536// do it in two separate events
537//
538Function AppendModelToTarget(ba) : ButtonControl
539        STRUCT WMButtonAction &ba
540
541        String coefStr,suffix,yWStr,xWStr,folderStr,funcStr
542       
543        switch( ba.eventCode )
544                case 2: // mouse up                     
545                        ControlInfo/W=WrapperPanel popup_2
546                        coefStr=S_Value
547                       
548                        ControlInfo/W=WrapperPanel popup_1
549                        funcStr=S_Value
550                        suffix = getModelSuffix(funcStr)
551                       
552                        // check for smeared or smeared function
553                        if(stringmatch(coefStr, "smear*" )==1)
554                                //it's a smeared model
555                                ControlInfo/W=WrapperPanel popup_0
556                                folderStr=S_Value
557                                xWStr = "root:"+folderStr+":smeared_qvals"
558                                ywStr = "root:"+folderStr+":smeared_"+suffix
559                        else
560                                // it's not, so it's in the root folder
561                                xWStr = "xwave_"+suffix
562                                yWStr = "ywave_"+suffix
563                        endif
564                       
565                        Wave/Z yw = $yWStr
566                        Wave/Z xw = $xWStr
567                        if(WaveExists(yw) && WaveExists(xw))
568                                AppendtoGraph yw vs xw
569                        else
570                                DoAlert 0,"The selected model has not been plotted for the selected data set."
571                        endif
572                        break
573        endswitch
574       
575        return 0
576End
577
578
579// this should parse the panel and call the FitWrapper() function
580Function DoTheFitButton(ba) : ButtonControl
581        STRUCT WMButtonAction &ba
582
583        String folderStr,funcStr,coefStr
584        Variable useCursors,useEps,useConstr,useResiduals,useTextBox, useRescaleAxis
585       
586        switch( ba.eventCode )
587                case 2: // mouse up
588                        ControlInfo/W=WrapperPanel popup_0
589                        folderStr=S_Value
590                       
591                        ControlInfo/W=WrapperPanel popup_1
592                        funcStr=S_Value
593                       
594                        ControlInfo/W=WrapperPanel popup_2
595                        coefStr=S_Value
596                       
597                        ControlInfo/W=WrapperPanel check_0
598                        useCursors=V_Value
599                        ControlInfo/W=WrapperPanel check_1
600                        useEps=V_Value
601                        ControlInfo/W=WrapperPanel check_2
602                        useConstr=V_Value
603                       
604                        ControlInfo/W=WrapperPanel check_6
605                        useResiduals=V_Value
606                       
607                        ControlInfo/W=WrapperPanel check_7
608                        useTextBox = V_Value
609                       
610                        ControlInfo/W=WrapperPanel check_8
611                        useRescaleAxis = V_Value
612                       
613                        if(!CheckFunctionAndCoef(funcStr,coefStr))
614                                DoAlert 0,"The coefficients and function type do not match. Please correct the selections in the popup menus."
615                                break
616                        endif
617                       
618                        FitWrapper(folderStr,funcStr,coefStr,useCursors,useEps,useConstr,useResiduals,useTextBox,useRescaleAxis)
619                       
620                        //      DoUpdate (does not work!)
621                        //?? why do I need to force an update ??
622                        if(!exists("root:"+folderStr+":"+coefStr))
623                                Wave w=$coefStr
624                        else
625                                Wave w=$("root:"+folderStr+":"+coefStr) //smeared coefs in data folder
626                        endif
627                        w[0] += 1e-6
628                        w[0] -= 1e-6
629
630       
631                                       
632                        break
633        endswitch
634       
635        return 0
636End
637
638Function CheckFunctionAndCoef(funcStr,coefStr)
639        String funcStr,coefStr
640       
641        SVAR listStr=root:Packages:NIST:coefKWStr
642        String properCoefStr = StringByKey(funcStr, listStr  ,"=",";",0)
643        if(cmpstr("",properCoefStr)==0)
644                return(0)               //false, no match found, so properCoefStr is returned null
645        endif
646        if(cmpstr(coefStr,properCoefStr)==0)
647                return(1)               //true, the coef is the correct match
648        endif
649        return(0)                       //false, wrong coef
650End
651
652/////////////////////////////////
653
654// wrapper to do the desired fit
655//
656// folderStr is the data folder for the desired data set
657//
658//
659Function FitWrapper(folderStr,funcStr,coefStr,useCursors,useEps,useConstr,useResiduals,useTextBox,useRescaleAxis)
660        String folderStr,funcStr,coefStr
661        Variable useCursors,useEps,useConstr,useResiduals,useTextBox,useRescaleAxis
662
663        String suffix=getModelSuffix(funcStr)
664       
665        SetDataFolder $("root:"+folderStr)
666        if(!exists(coefStr))
667                // must be unsmeared model, work in the root folder
668                SetDataFolder root:                             
669                if(!exists(coefStr))            //this should be fine if the coef filter is working, but check anyhow
670                        DoAlert 0,"the coefficient and data sets do not match"
671                        return 0
672                endif
673        endif
674               
675        WAVE cw=$(coefStr)     
676        Wave hold=$("Hold_"+suffix)
677        Wave/T lolim=$("LoLim_"+suffix)
678        Wave/T hilim=$("HiLim_"+suffix)
679       
680        if(useEps)
681                Wave eps=$("epsilon_"+suffix)
682        endif
683// fill a struct instance whether I need one or not
684        String DF="root:"+folderStr+":"
685       
686        Struct ResSmearAAOStruct fs
687        WAVE/Z resW = $(DF+folderStr+"_res")                    //these may not exist, if 3-column data is used
688        WAVE/Z fs.resW =  resW
689        WAVE yw=$(DF+folderStr+"_i")
690        WAVE xw=$(DF+folderStr+"_q")
691        WAVE sw=$(DF+folderStr+"_s")
692        Wave fs.coefW = cw
693        Wave fs.yW = yw
694        Wave fs.xW = xw
695       
696        Duplicate/O yw $(DF+"FitYw")
697        WAVE fitYw = $(DF+"FitYw")
698        fitYw = NaN
699       
700        Variable useResol=0,isUSANS=0,val
701        if(stringmatch(funcStr, "Smear*"))              // if it's a smeared function, need a struct
702                useResol=1
703        endif
704        if(dimsize(resW,1) > 4)
705                isUSANS=1
706        endif
707       
708        // do not construct constraints for any of the coefficients that are being held
709        // -- this will generate an "unknown error" from the curve fitting
710        // -- if constraints are not used, the constr wave is killed. This apparently
711        // confuses the /NWOK flag, since there is not even a null reference present. So generate one.
712        if(useConstr)
713                Make/O/T/N=0 constr
714                String constraintExpression
715                Variable i, nPnts=DimSize(lolim, 0),nextRow=0
716                for (i=0; i < nPnts; i += 1)
717                        if (strlen(lolim[i]) > 0 && hold[i] == 0)
718                                InsertPoints nextRow, 1, constr
719                                sprintf constraintExpression, "K%d > %s", i, lolim[i]
720                                constr[nextRow] = constraintExpression
721                                nextRow += 1
722                        endif
723                        if (strlen(hilim[i]) > 0 && hold[i] == 0)
724                                InsertPoints nextRow, 1, constr
725                                sprintf constraintExpression, "K%d < %s", i, hilim[i]
726                                constr[nextRow] = constraintExpression
727                                nextRow += 1
728                        endif
729                endfor
730        else
731                Wave/T/Z constr = constr
732                KillWaves/Z constr
733                Wave/T/Z constr = constr                //this is intentionally a null reference
734        endif
735
736        // 20JUN if useCursors is true, and there are no cursors on the specified data set, uncheck and set to false
737        // this is a last line of defense, and should never actually do anything...
738        if(useCursors)
739                useCursors = AreCursorsCorrect(folderStr)
740        endif
741        //if useCursors, and the data is USANS, need to recalculate the matrix if the range is new
742        Variable pt1,pt2,newN,mPt1,mPt2
743        String noteStr
744        if(useCursors && isUSANS )
745                //where are the cursors, and what is the status of the current matrix?
746                if(pcsr(A) > pcsr(B))
747                        pt1 = pcsr(B)
748                        pt2 = pcsr(A)
749                else
750                        pt1 = pcsr(A)
751                        pt2 = pcsr(B)
752                endif
753               
754                noteStr = note(resW)
755                mPt1 = NumberByKey("P1",noteStr,"=",";")
756                mPt2 = NumberByKey("P2",noteStr,"=",";")
757                if((mPt1 != pt1) || (mPt2 != pt2) )
758                        // need to recalculate
759                        USANS_RE_CalcWeights(folderStr,pt1,pt2)
760                        Print "Done recalculating the matrix"
761                endif
762               
763                Wave trimResW=$(DF+folderStr+"_res"+"t")        //put the trimmed resW in the struct for the fit!
764                Wave fs.resW=trimResW
765        endif
766        if(useCursors)
767                //find the points so that genetic optimization can use them
768                if(pcsr(A) > pcsr(B))
769                        pt1 = pcsr(B)
770                        pt2 = pcsr(A)
771                else
772                        pt1 = pcsr(A)
773                        pt2 = pcsr(B)
774                endif
775        else
776                //if cursors are not being used, find the first and last points of the data set, and pass them
777                pt1 = 0
778                pt2 = numpnts(yw)-1
779        endif
780               
781// create these variables so that FuncFit will set them on exit
782        Variable/G V_FitError=0                         //0=no err, 1=error,(2^1+2^0)=3=singular matrix
783        Variable/G V_FitQuitReason=0            //0=ok,1=maxiter,2=user stop,3=no chisq decrease
784
785        NVAR useGenCurveFit = root:Packages:NIST:gUseGenCurveFit
786// don't use the auto-destination with no flag, it doesn't appear to work correctly
787// dispatch the fit
788
789// currently, none of the fit functions are defined as threadsafe, so I don't think that the /NTHR flag really
790// does anything. The functions themselves can be threaded since they are AAO, and that is probably enough,
791// since it doesn't make much sense to thread threads. In addition, there is a little-publicized warning
792// in the WM help file that /C=texWave cannot be used to specify constraints for threadsafe functions!
793// The textwave would have to be parsed into a constraint matrix first, then passed as /C={cMat,cVec}.
794// -- just something to watch out for.
795
796// now two more flags... ,useResiduals,useTextBox
797        Variable tb = 1+2+4+8+16+256+512                //See CurveFit docs for bit settings for /TBOX flag
798
799        do
800                Variable t0 = stopMStimer(-2)           // corresponding print is at the end of the do-while loop (outside)
801
802
803                if(useGenCurveFit)
804               
805#if !(exists("GenCurveFit"))
806                        // XOP not available
807                        useGenCurveFit = 0
808                        Abort "Genetic Optimiztion XOP not available. Reverting to normal optimization."       
809#endif
810                        //send everything to a function, to reduce the clutter
811                        // useEps and useConstr are not needed
812                        // pass the structure to get the current waves, including the trimmed USANS matrix
813                        //
814                        // I don't know that GetCurveFit can do residuals, so I'm not passing that flag, or the text box flag
815                        //
816                        Variable chi,pt
817
818                        chi = DoGenCurveFit(useResol,useCursors,sw,fitYw,fs,funcStr,getHStr(hold),val,lolim,hilim,pt1,pt2)
819                        pt = val
820
821                        break
822                       
823                endif
824
825// for Igor 7 -- add the flag /N=0 to force the curve fit to update at each iteration. Some loss in speed
826//   over the new default of no update, but the user can see what is happening.
827               
828                // now useCursors, useEps, and useConstr are all handled w/ /NWOK
829                // so there are only three conditions to test == 1 + 3 + 3 + 1 = 8 conditions
830               
831                if(useResol && useResiduals && useTextBox)              //do it all
832                        FuncFit/H=getHStr(hold) /N=0 /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
833                        break
834                endif
835               
836                if(useResol && useResiduals)            //res + resid
837                        FuncFit/H=getHStr(hold) /N=0 /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
838                        break
839                endif
840
841               
842                if(useResol && useTextBox)              //res + text
843                        FuncFit/H=getHStr(hold) /N=0 /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
844                        break
845                endif
846               
847                if(useResol)            //res only
848//                      Print "timing test for Cylinder_PolyRadius---"
849//                      Variable t0 = stopMStimer(-2)
850
851                        FuncFit/H=getHStr(hold) /N=0 /M=2 /NTHR=0 $funcStr cw, yw[pt1,pt2] /X=xw /W=sw /I=1 /E=eps /D=fitYw /C=constr /STRC=fs /NWOK
852                       
853//                      t0 = (stopMSTimer(-2) - t0)*1e-6
854//                      Printf  "CylPolyRad fit time using res and eps and /NTHR=0 time = %g seconds\r\r",t0
855//                      cw[0] = .01
856//                      cw[1] = 20
857//                      cw[2] = 400
858//                      cw[3] = 0.2
859//                      cw[4] = 3e-6
860//                      cw[5] = 0.0
861//                     
862//                      t0 = stopMSTimer(-2)
863//                      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
864//                      t0 = (stopMSTimer(-2) - t0)*1e-6
865//                      Printf  "CylPolyRad fit time using res and eps and NO THREADING time = %g seconds\r\r",t0
866                        break
867                endif
868                       
869               
870               
871/////   same as above, but all without useResol (no /STRC flag)
872                if(useResiduals && useTextBox)          //resid+ text
873                        FuncFit/H=getHStr(hold) /N=0 /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
874                        break
875                endif
876               
877                if(useResiduals)                //resid
878                        FuncFit/H=getHStr(hold) /N=0 /M=2 /NTHR=0 $funcStr cw, yw[pt1,pt2] /X=xw /W=sw /I=1 /E=eps /D=fitYw /C=constr /R /NWOK
879                        break
880                endif
881
882               
883                if(useTextBox)          //text
884                        FuncFit/H=getHStr(hold) /N=0 /M=2 /NTHR=0 /TBOX=(tb) $funcStr cw, yw[pt1,pt2] /X=xw /W=sw /I=1 /E=eps /D=fitYw /C=constr /NWOK
885                        break
886                endif
887               
888                //just a plain vanilla fit
889
890                FuncFit/H=getHStr(hold) /N=0 /M=2 /NTHR=0 $funcStr cw, yw[pt1,pt2] /X=xw /W=sw /I=1 /E=eps /D=fitYw /C=constr /NWOK
891               
892        while(0)
893       
894        t0 = (stopMSTimer(-2) - t0)*1e-6
895        Printf  "fit time = %g seconds\r\r",t0
896       
897       
898        // append the fit
899        // need to manage duplicate copies
900        // Don't plot the full curve if cursors were used (set fitYw to NaN on entry...)
901        String traces=TraceNameList("", ";", 1 )                //"" as first parameter == look on the target graph
902        if(strsearch(traces,"FitYw",0) == -1 )
903                if(useGenCurveFit && useCursors)
904                        WAVE trimX = trimX
905                        AppendtoGraph fitYw vs trimX
906                else
907                        AppendToGraph FitYw vs xw
908                endif
909        elseif (strsearch(traces,"FitYw_RA",0) == -1)
910                RemoveFromGraph FitYw
911                if(useGenCurveFit && useCursors)
912                        WAVE trimX = trimX
913                        AppendtoGraph fitYw vs trimX
914                else
915                        AppendToGraph FitYw vs xw
916                endif
917        else
918                RemoveFromGraph FitYw_RA
919                if(useGenCurveFit && useCursors)
920                        WAVE trimX = trimX
921                        AppendtoGraph fitYw vs trimX
922                else
923                        AppendToGraph FitYw vs xw
924                endif
925        endif
926        ModifyGraph lsize(FitYw)=2,rgb(FitYw)=(0,0,0)
927       
928        DoUpdate                //force update of table and graph with fitted values (why doesn't this work? - the table still does not update)
929
930//      this is the top graph, and I do this in Igor 7 to force update of the infoBox and for the report to appear
931        DoWindow/F $(WinName(0,1))     
932        // report the results (to the panel?)
933        if(useGenCurveFit)
934                V_chisq = chi
935                V_npnts = pt
936        endif
937        print "V_chisq = ",V_chisq
938        print cw
939        WAVE/Z w_sigma
940        print w_sigma
941        String resultStr=""
942        Variable maxRelError=0
943       
944        if(waveexists(W_sigma))
945                //append it to the table, if it's not already there
946                CheckDisplayed/W=WrapperPanel#T0 W_sigma
947                if(V_flag==0)
948                        //not there, append it
949                        AppendtoTable/W=wrapperPanel#T0 W_sigma
950                else
951                        //remove it, and put it back on to make sure it's the right one (do I need to do this?)
952                        // -- not really, since any switch of the function menu takes W_Sigma off
953                endif
954                // then do I want to color it if the errors are horrible?
955                Duplicate/O cw, relError
956                relError = W_sigma/cw
957                maxRelError = WaveMax(relError)
958                if(maxRelError > kRelErrorTolerance)
959                        ModifyTable/W=wrapperPanel#T0 style(W_sigma)=1,rgb(W_sigma)=(65535,0,0)
960                else
961                        ModifyTable/W=wrapperPanel#T0 style=0,rgb=(0,0,0)
962        endif
963       
964        endif
965       
966        //now re-write the results
967        sprintf resultStr,"Chi^2 = %g  Sqrt(X^2/N) = %g",V_chisq,sqrt(V_chisq/V_Npnts)
968        resultStr = PadString(resultStr,63,0x20)
969        DoWIndow/F WrapperPanel
970        GroupBox grpBox_2 title=resultStr
971        ControlUpdate/W=WrapperPanel grpBox_2
972        sprintf resultStr,"FitErr = %s : FitQuit = %s",W_ErrorMessage(V_FitError),W_QuitMessage(V_FitQuitReason)
973        resultStr = PadString(resultStr,63,0x20)
974        GroupBox grpBox_3 title=resultStr
975        ControlUpdate/W=WrapperPanel grpBox_3
976       
977        Variable yesSave=0,yesReport=0
978        ControlInfo/W=WrapperPanel check_4
979        yesReport = V_Value
980        ControlInfo/W=WrapperPanel check_5
981        yesSave = V_Value
982       
983       
984        if(yesReport)
985                String parStr=GetWavesDataFolder(cw,1)+ WaveList("*param*"+"_"+suffix, "", "TEXT:1," )          // this is *hopefully* one wave
986                String topGraph= WinName(0,1)   //this is the topmost graph
987       
988                DoUpdate                //force an update of the graph before making a copy of it for the report
989
990                //if GenCurveFit used, V_startRow and V_endRow may not exist - so read the cursors? but the cursors may not be used, so
991                // there won't be anything on the graph... but pt1 and pt2 are set and passed!. The V_ variables are more foolproof
992                // so keep these for the "normal" report
993                //
994                if(useGenCurveFit)     
995                        W_GenerateReport(funcStr,folderStr,$parStr,cw,yesSave,V_chisq,W_sigma,V_npnts,V_FitError,V_FitQuitReason,pt1,pt2,topGraph)
996                else
997                        W_GenerateReport(funcStr,folderStr,$parStr,cw,yesSave,V_chisq,W_sigma,V_npnts,V_FitError,V_FitQuitReason,V_startRow,V_endRow,topGraph)
998                endif
999        endif
1000       
1001        //Rescale the Plot depending on the user choice
1002        if(useRescaleAxis)
1003                string ctrlName = "GoRescale"
1004                RescalePlot(ctrlName)
1005        elseif (DataFolderExists("root:Packages:NIST:RescaleAxis"))
1006                SetDataFolder root:
1007                String PlotGraph= WinName(0,1)  //this is the topmost graph
1008                DoWindow/F $PlotGraph
1009               
1010                GetWindow/Z $PlotGraph, wavelist
1011                if (V_flag != 0)
1012                        DoPrompt/Help="" "I couldn't find the graph"
1013                        Abort
1014                endif
1015               
1016                wave/t W_Wavelist
1017               
1018                variable j
1019                string temp
1020                SetDataFolder root:Packages:NIST:RescaleAxis
1021                if (exists("W_WaveList")==1)
1022                        KillWaves/Z root:Packages:NIST:RescaleAxis:W_WaveList
1023                endif
1024                MoveWave root:W_WaveList, root:Packages:NIST:RescaleAxis:W_WaveList
1025               
1026                for(i=0; i < numpnts(W_Wavelist)/3; i+=1)
1027                        temp = W_WaveList[i][0]
1028                        if(stringmatch(temp, "*_RA"))
1029               
1030                                string WaveDataFolder, WaveToRescale
1031                                WaveDataFolder = ReplaceString(W_WaveList[i][0], W_WaveList[i][1], "")
1032                                if(strlen(WaveDataFolder)==0)
1033                                        WaveDataFolder = ":"
1034                                endif
1035                                WaveDataFolder = "root"+WaveDataFolder 
1036                                SetDataFolder $WaveDataFolder
1037                                temp = RemoveEnding(temp, "_RA")
1038                               
1039                                string xwave, ywave, oldywave, swave
1040                                if(exists(temp)==1)
1041                                        Wave/T WaveString = $temp
1042                                        WaveToRescale = temp
1043                                        if (stringmatch(WaveToRescale, "*_i"))
1044                                                DoWindow/F PlotGraph
1045                                                oldywave = WaveToRescale+"_RA"
1046                                                ywave = WaveToRescale
1047                                                replacewave/Y/W=$PlotGraph trace=$oldywave, $ywave
1048                                                xwave = RemoveEnding(WaveToRescale, "_i")+"_q"
1049                                                replacewave/X/W=$PlotGraph trace=$ywave, $xwave
1050                                                ModifyGraph log=0
1051                                                swave = RemoveEnding(WaveToRescale, "_i")+"_s"
1052                                                if(exists(swave)==1)
1053                                                        ErrorBars/W=$PlotGraph $ywave, Y wave=($swave,$swave)   
1054                                                endif
1055                                        elseif(stringmatch(WaveToRescale, "smeared*") && stringmatch(WaveToRescale, "!*_qvals"))
1056                                                oldywave = WaveToRescale+"_RA"
1057                                                ywave = WaveToRescale
1058                                                replacewave/Y/W=$PlotGraph trace=$oldywave, $ywave
1059                                                xwave = "smeared_qvals"
1060                                                replacewave/X/W=$PlotGraph trace=$ywave, $xwave
1061                                                ModifyGraph log=0
1062                                        elseif(stringmatch(WaveToRescale,"ywave*"))
1063                                                oldywave = WaveToRescale+"_RA"
1064                                                ywave = WaveToRescale
1065                                                xwave = ReplaceString("ywave",ywave,"xwave")
1066                                                replacewave/Y/W=$PlotGraph trace=$oldywave, $ywave
1067                                                replacewave/X/W=$PlotGraph trace=$ywave, $xwave                                 
1068                                        endif
1069                                SetDataFolder root:Packages:NIST:RescaleAxis
1070                                endif
1071                        endif
1072                endfor
1073                KillWaves/Z W_WaveList
1074                modifygraph log=1
1075                Label left "I(q)"
1076                Label bottom "q (A\S-1\M)"
1077        Endif
1078
1079        SetDataFolder root:
1080        return(0)
1081End
1082
1083// parse something off of a table, or ?
1084Function/S getHStr(hold)
1085        Wave hold
1086       
1087        String str=""
1088        Variable ii
1089        for(ii=0;ii<numpnts(hold);ii+=1)
1090                str += num2str(hold[ii])
1091        endfor
1092
1093//      print str
1094        if(strsearch(str, "1", 0) == -1)
1095                return ("")
1096        else
1097                return(str)
1098        endif
1099End
1100
1101//taken from SRK Auto_Fit, and modified to work better with FitWrapper
1102//must have AutoGraph as the name of the graph window (any size)
1103// func is the name of the function (for print only)
1104//par and coef are the exact names of the waves
1105//yesSave==1 will save the file(name=func+time)
1106//
1107Function W_GenerateReport(func,dataname,param,ans,yesSave,chiSq,sigWave,npts,fitErr,fitQuit,fitStart,fitEnd,topGraph)
1108        String func,dataname
1109        Wave/T param
1110        Wave ans
1111        Variable yesSave,chiSq
1112        Wave sigWave
1113        Variable npts,fitErr,fitQuit,fitStart,fitEnd
1114        String topGraph
1115       
1116        String str,pictStr="P_"
1117        String nb="Report"
1118               
1119        // bring report up
1120        DoWindow/F Report
1121        if (V_flag == 0)                // Report notebook doesn't exist ?
1122                NewNotebook/W=(10,45,550,620)/F=1/N=Report as "Report"
1123        endif
1124        // delete old stuff
1125        Notebook $nb selection={startOfFile, endOfFile}, text="\r", selection={startOfFile, startOfFile}
1126       
1127        //setup
1128        Notebook $nb defaultTab=36, statusWidth=252, pageMargins={72,72,72,72}
1129        Notebook $nb showRuler=1, rulerUnits=1, updating={1, 60}
1130        Notebook $nb newRuler=Normal, justification=0, margins={0,0,468}, spacing={0,0,0}, tabs={}, rulerDefaults={"Geneva",10,0,(0,0,0)}
1131//     
1132        // insert title
1133        Notebook $nb newRuler=Title, justification=1, rulerDefaults={"Times", 16, 1, (0, 0, 0)}
1134        sprintf str, "Fit to %s, %s, %s\r\r", func,Secs2Date(datetime, 0), time()
1135        Notebook $nb ruler=Title, text=str
1136       
1137        // insert fit results
1138        Variable num=numpnts(ans),ii=0
1139        Notebook $nb ruler=Normal
1140        Notebook $nb  margins={18,18,504}, tabs={63 + 3*8192}
1141        str = "Data file: " + dataname + "\r\r"
1142        Notebook $nb text=str
1143        Notebook $nb ruler=Normal
1144        Notebook $nb margins={18,18,504}, tabs={144,234,252}
1145        do
1146                sprintf str, "%s = \t%g\t±\t%g\r", param[ii],ans[ii],sigwave[ii]
1147                Notebook $nb text=str
1148                ii+=1
1149        while(ii<num)
1150       
1151        //
1152        // no "fitted range" for 2D data, so make sure that this exists before using it
1153        Wave/Z dataXw = $("root:"+dataname+":"+dataname+"_q")   
1154        //
1155        Notebook $nb ruler=Normal
1156        Notebook $nb  margins={18,18,504}, tabs={63+3*8192}, fStyle=1, textRGB=(65000,0,0)
1157       
1158        sprintf str,"chisq = %g\r",chisq
1159        Notebook $nb textRGB=(65000,0,0),fstyle=1,text=str
1160        sprintf str,"Npnts = %g \t\t Sqrt(X^2/N) = %g\r",npts,sqrt(chiSq/npts)
1161        Notebook $nb textRGB=(0,0,0),fstyle=0, text=str
1162        if(WaveExists(dataXw))
1163                sprintf str "Fitted range = [%d,%d] = %g < Q < %g\r",fitStart,fitEnd,dataXw(fitStart),dataXw(fitEnd)
1164                Notebook $nb textRGB=(0,0,0),fstyle=0, text=str
1165        endif
1166        sprintf str,"FitError = %s\t\tFitQuitReason = %s\r",W_ErrorMessage(FitErr),W_QuitMessage(FitQuit)
1167        Notebook $nb textRGB=(65000,0,0),fstyle=1,text=str
1168        Notebook $nb ruler=Normal
1169       
1170        // insert graphs
1171        if(WaveExists(dataXw))
1172//              Notebook $nb picture={$topGraph(0, 0, 400, 300), -5, 1}, text="\r"
1173                Notebook $nb scaling={50, 50}, picture={$topGraph(0, 0, 800, 600), -5, 1}, text="\r"
1174        //
1175        else            //must be 2D Gizmo
1176                Execute "ExportGizmo Clip"                      //this ALWAYS is a PICT or BMP. Gizmo windows are different...
1177                LoadPict/Q/O "Clipboard",tmp_Gizmo
1178                Notebook $nb picture={tmp_Gizmo(0, 0, 800, 600), 0, 1}, text="\r"
1179        endif
1180       
1181        // show the top of the report
1182        Notebook $nb  selection= {startOfFile, startOfFile},  findText={"", 1}
1183       
1184        //save the notebook and the graphic file
1185        // saving with a unique name can be an issue if there are a lot of files with similar names
1186        // and the fit function has a long name
1187        if(yesSave)
1188                String nameStr
1189                // function first               
1190//              nameStr=CleanupName(func,0)
1191//              nameStr += "_"+dataname
1192//              nameStr = ReplaceString("Smeared",nameStr,"Sm_")                //if Smeared function, shorten the name
1193                // -- or
1194                // data first
1195                nameStr = dataname+"_"
1196                nameStr += CleanupName(func,0)
1197                nameStr = ReplaceString("Smeared",nameStr,"Sm_")                //if Smeared function, shorten the name
1198
1199                //make sure the name is no more than 31 characters
1200                namestr = namestr[0,26]         //if shorter than 31, this will NOT pad to 31 characters
1201                nameStr += ".ifn"                       //extension is needed, otherwise the files are not recognized on Windows
1202               
1203                Print "file saved as ",nameStr
1204                SaveNotebook /O/P=home/S=2 $nb as nameStr
1205                //save the graph separately as a PNG file, 2x screen
1206                pictStr += nameStr
1207                pictStr = pictStr[0,24]+".png"          //need a shorter name - only 29 characters allowed - why?
1208//              DoWindow/F $topGraph
1209                // E=-5 is png @screen resolution
1210                // E=2 is PICT @2x screen resolution
1211///             SavePICT /E=-5/O/P=home /I/W=(0,0,3,3) as pictStr
1212                if(WaveExists(dataXw))
1213                        SavePICT /E=-5/O/P=home/WIN=$topGraph /W=(0,0,800,600) as pictStr
1214                else
1215                        Execute "ExportGizmo /P=home as \""+pictStr+"\""                //this won't be of very high quality
1216                        //SavePICT /E=-5/O/P=home/WIN=$topGraph /W=(0,0,400,300) as pictStr
1217                endif
1218        Endif
1219       
1220        // ???maybe print the notebook too?
1221End
1222
1223Function/S W_ErrorMessage(code)
1224        Variable code
1225       
1226        switch (code)
1227                case 0:
1228                        return "No Error"
1229                        break
1230                case 3: //2^0 + 2^1
1231                        return "Singular Matrix"
1232                        break
1233                case 5:         //(2^0 + 2^2)
1234                        return "Out of Memory"
1235                        break
1236                case 9:         //(2^0 + 2^3)
1237                        return "Func= NaN or Inf"
1238                        break
1239                default:
1240                        return "Unknown error code "+num2str(code)
1241        endswitch
1242end
1243
1244Function/S W_QuitMessage(code)
1245        Variable code
1246       
1247        switch (code)
1248                case 0:
1249                        return "No Error"
1250                        break
1251                case 1:
1252                        return "Max iterations - re-run fit"
1253                        break
1254                case 2:
1255                        return "User terminated fit"
1256                        break
1257                case 3:
1258                        return "No decrease in chi-squared"
1259                        break
1260                default:
1261                        return "Unknown Quit code "+num2str(code)
1262        endswitch
1263end
1264
1265Function UseInfoTextBoxCheckProc(cba) : CheckBoxControl
1266        STRUCT WMCheckboxAction &cba
1267
1268        switch( cba.eventCode )
1269                case 2: // mouse up
1270                        Variable checked = cba.checked
1271                        if(checked)
1272                                //print "checked, use textBox in the next fit"
1273                        else
1274                                //print "unchecked, ask to remove TextBox from the graph"
1275                                ControlInfo/W=WrapperPanel popup_0
1276                                RemoveTextBox(S_value)
1277                        endif
1278                        break
1279        endswitch
1280
1281        return 0
1282End
1283
1284//does not report an error if the text box is not there
1285// -- so I'll just be lazy and not check to see if it's there
1286//
1287Function RemoveTextBox(folderStr)
1288        String folderStr
1289       
1290        DoAlert 1,"Remove the TextBox from the graph?"
1291        if(V_flag == 1)
1292                String str = "CF_"+folderStr+"_i"
1293                TextBox/K/N=$str
1294        endif
1295        return(0)
1296End
1297
1298Function UseResidualsCheckProc(cba) : CheckBoxControl
1299        STRUCT WMCheckboxAction &cba
1300
1301        switch( cba.eventCode )
1302                case 2: // mouse up
1303                        Variable checked = cba.checked
1304                        if(checked)
1305                                //print "checked, use them in the next fit"
1306                        else
1307                                //print "unchecked, ask to remove residuals from the graph"
1308                                ControlInfo/W=WrapperPanel popup_0
1309                                RemoveResiduals(S_value)
1310                        endif
1311                        break
1312        endswitch
1313
1314        return 0
1315End
1316
1317// the default name from the /R flag is "Res_" + yWaveName
1318//
1319// better to find the wave that starts with "Res_" and remove that one in case the
1320// wave names get too long
1321//
1322// the difficulty now is that the residual wave ends up in root: and not with the data....
1323// -- not really a problem, but adds to clutter
1324Function RemoveResiduals(folderStr)
1325        String folderStr
1326       
1327        String list="",topWin=""
1328        Variable num,ii
1329        String str
1330
1331        DoAlert 1,"Remove the residuals from the graph?"
1332        if(V_flag == 1)
1333//              String topGraph= WinName(0,1)   //this is the topmost graph
1334                list=TraceNameList("", ";", 1 )         //"" as first parameter == look on the target graph
1335                num=ItemsInList(list)
1336               
1337                for(ii=0;ii<num;ii+=1)
1338                        str = StringFromList(ii, list ,";")
1339                        if(strsearch(str, "Res_", 0) != -1)
1340                                RemoveFromGraph $str
1341                        endif
1342                endfor
1343       
1344                SetDataFolder root:
1345        endif
1346       
1347        return(0)
1348End
1349
1350Function Toggle2DControlsCheckProc(cba) : CheckBoxControl
1351        STRUCT WMCheckboxAction &cba
1352
1353        switch( cba.eventCode )
1354                case 2: // mouse up
1355                        Variable checked = cba.checked
1356                        if(checked)
1357                                //print "change the buttons to 2D"
1358                                Button button_0,proc=Do2DFitButtonProc,title="Do 2D Fit"
1359                                Button button_1,size={120,20},proc=Plot2DFunctionButtonProc,title="Plot 2D Function"
1360                                Button button_2,size={100,20},proc=Append2DModelButtonProc,title="Append 2D"
1361                                Button button_3,size={100,20},proc=Load2DDataButtonProc,title="Load 2D Data"
1362                               
1363                                Button button_2D_0,pos={550,60},size={70,20},proc=LogToggle2DButtonProc,title="Log/Lin"
1364                                Button button_2D_1,pos={520,37},size={100,20},proc=Plot2DButtonProc,title="Plot 2D Data"
1365                               
1366                                Button button_2D_0,disable=0            //visible again, and enabled
1367                                Button button_2D_1,disable=0
1368                               
1369                                CheckBox check_6,disable=1                      //info box and residual check, remove these from view
1370                                CheckBox check_7,disable=1
1371                                CheckBox check_8,disable=1
1372                        else
1373                                //print "unchecked, change them back to 1D"
1374                                Button button_0,pos={520,93},size={100,20},proc=DoTheFitButton,title="Do 1D Fit"
1375                                Button button_1,pos={280,57},size={120,20},proc=PlotModelFunction,title="Plot 1D Function"
1376                                Button button_2,pos={300,93},size={100,20},proc=AppendModelToTarget,title="Append 1D"
1377                                Button button_3,pos={300,20},size={100,20},proc=W_LoadDataButtonProc,title="Load 1D Data"
1378                               
1379                                Button button_2D_0,disable=3    //hide the extra 2D buttons, and disable
1380                                Button button_2D_1,disable=3
1381                               
1382                                CheckBox check_6,disable=0                      //info box and residual check, bring them back
1383                                CheckBox check_7,disable=0
1384                                CheckBox check_8,disable=0
1385                        endif
1386                        break
1387        endswitch
1388
1389        return 0
1390End
1391
1392// function to either add or remove the cursors from the topmost graph, as needed
1393
1394Function UseCursorsWrapperProc(cba) : CheckBoxControl
1395        STRUCT WMCheckboxAction &cba
1396
1397
1398        switch( cba.eventCode )
1399                case 2: // mouse up
1400               
1401                        // check to make sure there really is a "topmost" graph         
1402                        String topGraph= WinName(0,1)   //this is the topmost graph
1403                        if(cmpstr(topGraph,"")==0)      //no graphs, uncheck and exit
1404                                CheckBox check_0,value=0
1405                                return(0)
1406                        endif
1407                       
1408                        //if in 2D mode, just exit
1409                        ControlInfo/W=WrapperPanel check_3
1410                        if(V_Value == 1)
1411                                return (0)
1412                        endif
1413                               
1414                        String ciStr = CsrInfo(A , topGraph)
1415                       
1416                        ControlInfo/W=wrapperpanel popup_0
1417                        String folderStr=S_Value
1418                        String traceList = TraceNameList(topGraph, ";", 1 )             
1419               
1420                        Variable checked = cba.checked
1421                       
1422                        if(checked)
1423                                //print "add the cursors to the topmost graph, if the data set is there, or move them"
1424                                if(strlen(ciStr)==0 && strsearch(traceList, folderStr, 0) != -1 )               //no cursors && data is there
1425                                        ShowInfo
1426                                        Wave yw=$("root:"+folderStr+":"+folderStr+"_i")
1427                                        Cursor/P/W=$topGraph A, $(folderStr+"_i"),0
1428                                        Cursor/P/W=$topGraph/A=0 B, $(folderStr+"_i"),numpnts(yw)-1                     //deactivate the one at the high Q end
1429                                        DoUpdate
1430                                elseif (strlen(ciStr)!=0 && strsearch(traceList, folderStr, 0) != -1 ) //cursors present, but on wrong data
1431                                        Wave yw=$("root:"+folderStr+":"+folderStr+"_i")
1432                                        Cursor/P/W=$topGraph A, $(folderStr+"_i"),0                                                             //move the cursors
1433                                        Cursor/P/W=$topGraph/A=0 B, $(folderStr+"_i"),numpnts(yw)-1
1434                                        DoUpdate
1435                                endif
1436                               
1437                                AreCursorsCorrect(folderStr)
1438                        else
1439                                //print "unchecked, remove the cursors"
1440                                // go back to the full matrix for the resolution calculation (not if SANS data...)
1441                                if(waveExists($("root:"+folderStr+":weights_save")))
1442                                        Duplicate/O $("root:"+folderStr+":weights_save"), $("root:"+folderStr+":"+folderStr+"_res"),$("root:"+folderStr+":"+folderStr+"_rest")
1443                                endif
1444
1445                                HideInfo/W=$topGraph
1446                                Cursor/K A
1447                                Cursor/K B
1448                        endif
1449                        break
1450        endswitch
1451
1452        return 0
1453End
1454
1455// returns 1 if the specified data is on the top graph && has cursors on it
1456// returns 0 and unchecks the box if anything is wrong
1457//
1458// only call this function if the cursor box is checked, to uncheck it as needed
1459// if the box is unchecked, leave it be.
1460//
1461Function AreCursorsCorrect(folderStr)
1462        String folderStr
1463       
1464        String topGraph= WinName(0,1)   //this is the topmost graph
1465        if(cmpstr(topGraph,"")==0)      //no graphs, uncheck and exit
1466                CheckBox check_0,win=wrapperpanel,value=0
1467                return(0)
1468        endif
1469               
1470        String traceAisOn = CsrWave(A , "", 0)
1471        if(     strsearch(traceAisOn, folderStr, 0) == -1)              //data and cursors don't match
1472                CheckBox check_0,win=wrapperpanel,value=0
1473                HideInfo
1474                Cursor/K A
1475                Cursor/K B
1476                return(0)
1477        endif
1478       
1479        return(1)
1480End
1481
1482
1483
1484//////////////////////////////
1485//
1486// displays the covariance matrix for the current data set in the popup
1487// AND whatever was the last fit for that data set. it may not necessarily
1488// be the displayed function...
1489Function DisplayCovarianceMatrix()
1490
1491       
1492
1493        ControlInfo/W=wrapperpanel popup_0
1494        String folderStr=S_Value
1495
1496        ControlInfo/W=WrapperPanel popup_1
1497        String funcStr=S_Value
1498                       
1499        if(Stringmatch(funcStr,"Smear*"))               //simple test for smeared function
1500                if(DataFolderExists("root:"+folderStr))
1501                        SetDataFolder $("root:"+folderStr)
1502                else
1503                        SetDataFolder root:
1504                endif
1505        else
1506                SetDataFolder root:
1507        endif
1508       
1509        Wave M_Covar=M_Covar
1510        Duplicate/O M_Covar, CorMat      // You can use any name instead of CorMat
1511        CorMat = M_Covar[p][q]/sqrt(M_Covar[p][p]*M_Covar[q][q])
1512
1513        // clear the table (a subwindow)
1514        DoWindow/F CorMatPanel                          // ?? had to add this in during all of the cursor meddling...
1515        KillWindow CorMatPanel#T0
1516        Edit/W=(20,74,634,335)/HOST=CorMatPanel
1517        RenameWindow #,T0
1518        // get them onto the table
1519        // how do I get the parameter name?
1520        String param = getFunctionParams(funcStr)
1521        AppendtoTable/W=CorMatPanel#T0 $param
1522        AppendToTable/W=CorMatPanel#T0 CorMat
1523        ModifyTable/W=CorMatPanel#T0 width(Point)=0
1524
1525        GroupBox grpBox_1 title="Data set: "+folderStr
1526        GroupBox grpBox_2 title="Function: "+funcStr
1527
1528
1529        SetDataFolder root:
1530       
1531        return(0)
1532End
1533
1534
1535Window CorMatPanel()
1536        PauseUpdate; Silent 1           // building window...
1537        NewPanel /W=(459,44,1113,399)/N=CorMatPanel/K=1 as "Correlation Matrix"
1538        ModifyPanel fixedSize=1
1539       
1540        GroupBox grpBox_1 title="box 1",pos={10,20},size={0,0},frame=1,fSize=10,fstyle=1,fColor=(39321,1,1)
1541        GroupBox grpBox_2 title="box 2",pos={10,40},size={0,0},frame=1,fSize=10,fstyle=1,fColor=(39321,1,1)
1542
1543        Button button_1,pos={520,30},size={100,20},proc=CorMatHelpButtonProc,title="Help"
1544
1545        Edit/W=(20,74,634,335)/HOST=# 
1546        ModifyTable width(Point)=0
1547        RenameWindow #,T0
1548        SetActiveSubwindow ##
1549EndMacro
1550
1551
1552Proc DisplayCovariance()
1553        DoWindow/F CorMatPanel
1554        if(V_Flag==0)
1555                CorMatPanel()
1556        endif
1557       
1558        DisplayCovarianceMatrix()
1559
1560End
1561
1562//open the Help file for the Fit Manager
1563Function CorMatHelpButtonProc(ba) : ButtonControl
1564        STRUCT WMButtonAction &ba
1565
1566        switch( ba.eventCode )
1567                case 2: // mouse up
1568                        // click code here
1569                        DisplayHelpTopic/Z/K=1 "Covariance Matrix"
1570                        if(V_flag !=0)
1571                                DoAlert 0,"Help for the correlation matrix could not be found"
1572                        endif
1573                        break
1574        endswitch
1575
1576        return 0
1577End
1578
1579
1580//////////////////////////////////
1581// this is a snippet from Andy Nelson, posted at the Igor Exchange web site.
1582//
1583// search area appears to be a percent (so enter 10 to get +/- 10% variation in the parameter)
1584//
1585// TODO:
1586//              x- rename the function for just me
1587//              x- make the edata a mandatory parameter
1588//              x- remove rhs, lhs? or keep these if cursors were used to properly trim the data set
1589//              x- label the graph
1590//              x- make a panel to control this - to either pick a single parameter, or show all of them
1591//              x- have it re-use the same graph, not draw a (new) duplicate one
1592//              x- update it to use the AAO as the input function (new func template -- see Gauss Utils)
1593//              x- the wrapper must be data folder aware, and data set aware like in the Wrapper panel
1594//              x- need a different wrapper for smeared and unsmeared functions
1595//
1596//
1597
1598
1599
1600Proc MapChiSquared(paramNum,percent)
1601        Variable paramNum=0,percent=10
1602        Prompt paramNum, "Enter parameter number: "
1603        Prompt percent, "Enter percent variation +/- : "
1604
1605        fChiMap(paramNum,percent)
1606End
1607
1608
1609// this does the setup
1610Function fChiMap(paramNum,percent)
1611        Variable paramNum,percent
1612
1613        String folderStr,funcStr,coefStr
1614        Variable useCursors,useResol=0,pt1,pt2,minIndex
1615       
1616        ControlInfo/W=WrapperPanel popup_0
1617        folderStr=S_Value
1618       
1619        ControlInfo/W=WrapperPanel popup_1
1620        funcStr=S_Value
1621       
1622        ControlInfo/W=WrapperPanel popup_2
1623        coefStr=S_Value
1624       
1625        ControlInfo/W=WrapperPanel check_0
1626        useCursors=V_Value
1627       
1628       
1629// first, figure out where we are...
1630        String suffix=getModelSuffix(funcStr)
1631       
1632        SetDataFolder $("root:"+folderStr)
1633        if(!exists(coefStr))
1634                // must be unsmeared model, work in the root folder
1635                SetDataFolder root:                             
1636                if(!exists(coefStr))            //this should be fine if the coef filter is working, but check anyhow
1637                        DoAlert 0,"the coefficient and data sets do not match"
1638                        return 0
1639                endif
1640        endif
1641               
1642        WAVE cw=$(coefStr)
1643
1644
1645// test for smeared function
1646        if(stringmatch(funcStr, "Smear*"))              // if it's a smeared function, need a struct
1647                useResol=1
1648        endif
1649       
1650        // fill a struct instance whether I need one or not
1651        String DF="root:"+folderStr+":"
1652       
1653//      Struct ResSmearAAOStruct fs
1654//      WAVE/Z resW = $(DF+folderStr+"_res")                    //these may not exist, if 3-column data is used
1655//      WAVE/Z fs.resW =  resW
1656        WAVE yw=$(DF+folderStr+"_i")
1657        WAVE xw=$(DF+folderStr+"_q")
1658        WAVE sw=$(DF+folderStr+"_s")
1659//      Wave fs.coefW = cw
1660//      Wave fs.yW = yw
1661//      Wave fs.xW = xw
1662       
1663        if(useCursors)
1664                if(pcsr(A) > pcsr(B))
1665                        pt1 = pcsr(B)
1666                        pt2 = pcsr(A)
1667                else
1668                        pt1 = pcsr(A)
1669                        pt2 = pcsr(B)
1670                endif
1671        else
1672                //if cursors are not being used, find the first and last points of the data set, and pass them
1673                pt1 = 0
1674                pt2 = numpnts(yw)-1
1675        endif
1676       
1677        minIndex = chi2gen(funcStr,folderStr,xw,yw,sw,cw,paramNum,percent,pt1,pt2,useResol)
1678       
1679        WAVE chi2_map=chi2_map
1680        cw[paramNum] = pnt2x(chi2_map, minIndex)
1681       
1682        return(0)
1683End
1684
1685// this does the math for a single value of "whichParam"
1686Function chi2gen(funcStr,folderStr,xw,yw,sw,cw,whichParam,searchArea,lhs,rhs,useResol)
1687        String funcStr,folderStr
1688        Wave xw,yw,sw,cw      //        x data, y data, error wave, and coefficient wave
1689        variable whichParam, searchArea  //which of the parameters to you want to vary, how far from the original value do you want to search (%)
1690        variable lhs, rhs    //specify a region of interest in the data using a left hand side and right hand side.
1691        variable useResol               // =1 if smeared used
1692 
1693        variable originalvalue = cw[whichparam]
1694        variable range = originalValue * searchArea/100
1695        variable ii,err,minIndex
1696 
1697        duplicate/o yw, :theoretical_data, :chi2_data
1698        Wave theoretical_data, chi2_data
1699 
1700        make/o/n=50/d chi2_map
1701        setscale/I x,  originalvalue - range, originalvalue + range, chi2_map
1702 
1703        String DF="root:"+folderStr+":"
1704        String suffix=getModelSuffix(funcStr)
1705
1706        // fill a struct instance whether it is needed or not
1707        Struct ResSmearAAOStruct fs
1708        WAVE/Z resW = $(DF+folderStr+"_res")                    //these may not exist, if 3-column data is used
1709        WAVE/Z fs.resW =  resW
1710//              WAVE yw=$(DF+folderStr+"_i")
1711//              WAVE xw=$(DF+folderStr+"_q")
1712//              WAVE sw=$(DF+folderStr+"_s")
1713        Wave fs.coefW = cw
1714        Wave fs.yW = theoretical_data
1715        Wave fs.xW = xw
1716 
1717 
1718 
1719        for(ii=0 ; ii < numpnts(chi2_map) ; ii+=1)
1720                cw[whichparam] = pnt2x(chi2_map, ii)
1721 
1722                if(useResol)
1723                        FUNCREF SANSModelSTRUCT_proto func1=$funcStr
1724                        err = func1(fs)
1725                else
1726                        FUNCREF SANSModelAAO_proto func2=$funcStr
1727                        func2(cw,theoretical_data,xw)
1728                endif
1729               
1730                chi2_data = (yw-theoretical_data)^2
1731 
1732                chi2_data /= sw^2
1733
1734                Wavestats/q/R=[lhs, rhs] chi2_data
1735 
1736                chi2_map[ii] = V_avg * V_npnts
1737        endfor
1738 
1739        cw[whichparam] = originalvalue
1740 
1741        DoWindow/F Chi2
1742        if(V_flag==0)
1743                display/K=1/N=Chi2 chi2_map
1744                Label left "Chi^2"
1745        endif
1746
1747        String parStr=GetWavesDataFolder(cw,1)+ WaveList("*param*"+"_"+suffix, "", "TEXT:1," )          // this is *hopefully* one wave
1748        Wave/T parW = $parStr
1749        Label bottom parW[whichParam]
1750       
1751        WaveStats/Q chi2_map
1752        minIndex = V_minRowLoc
1753        Print "minimum at: ", minIndex,chi2_map[minIndex]
1754       
1755       
1756        killwaves/z theoretical_data, chi2_data
1757        return(minIndex)
1758End
1759 
1760
1761//////////////////////////////////
1762// this is based on a snippet from Andy Nelson, posted at the Igor Exchange web site.
1763// -- modified to do "manual fitting" - mapping out chi-squared along one or two directions
1764//////////////////////////////////
1765
1766Proc OpenManualFitPanel()
1767
1768        DoWindow/F ManualFitPanel
1769        if(V_flag==0)
1770                init_manualFit()
1771                ManualFitPanel()
1772        Endif
1773
1774End
1775
1776Function init_manualFit()
1777
1778        Variable/G root:gNumManualParam=0
1779        Variable/G root:gNumManualParam2=1
1780        Variable/G root:gCurrentChiSq=0
1781        Variable/G root:gNumManualSteps=50
1782       
1783        Make/O/D/N=1 root:chi2_map,root:testVals
1784        Make/O/D/N=(1,1) root:chi2D
1785       
1786        return(0)
1787end
1788
1789Window ManualFitPanel() : Panel
1790        PauseUpdate; Silent 1           // building window...
1791        NewPanel /W=(1170,44,1842,412) /K=1
1792        ModifyPanel cbRGB=(51664,44236,58982)
1793        DoWindow/C ManualFitPanel
1794       
1795//      ShowTools/A
1796        SetVariable setvar0,pos={25,10},size={150,15},title="Parameter number"
1797        SetVariable setvar0,limits={0,inf,1},value=root:gNumManualParam,disable=0
1798        SetVariable setvar3,pos={25,30},size={150,15},title="Parameter number"
1799        SetVariable setvar3,limits={0,inf,1},value=root:gNumManualParam2,disable=2
1800       
1801        CheckBox check0,pos={200,10},size={37,15},value=0,title="2D?",proc=Vary2DCheck
1802               
1803        Button button0,pos={25,55},size={100,20},title="Vary 100 %",proc=VaryPCTButton
1804        Button button1,pos={25,80},size={100,20},title="Vary 25 %",proc=VaryPCTButton
1805        Button button2,pos={25,105},size={100,20},title="Vary 5 %",proc=VaryPCTButton
1806        Button button3,pos={25,130},size={100,20},title="Vary 1 %",proc=VaryPCTButton
1807        SetVariable setvar1,pos={31,196},size={200,15},title="Current Chi-Squared"
1808        SetVariable setvar1,limits={0,0,0},value=root:gCurrentChiSq     
1809        SetVariable setvar2,pos={31,222},size={200,15},title="Number of steps"
1810        SetVariable setvar2,limits={5,500,1},value=root:gNumManualSteps
1811       
1812        //
1813        Display/W=(259,23,643,346)/HOST=# root:chi2_map vs root:testVals
1814        RenameWindow #,G0
1815        ModifyGraph mode=4,msize=1,rgb=(65535,0,0)
1816        ModifyGraph tick=2,mirror=1
1817//      Label left "Chi-squared"
1818//      Label bottom "degrees" 
1819        SetActiveSubwindow ##
1820               
1821EndMacro
1822
1823
1824Function Vary2DCheck(ctrlName,checked)
1825        String ctrlName
1826        Variable checked
1827       
1828        ControlInfo check0
1829        Variable isChecked = V_Value
1830       
1831        Wave chi2D=chi2D
1832        Wave chi2_map=chi2_map
1833        wave testVals=testVals
1834       
1835        if(isChecked)
1836                SetVariable setvar0,disable=0
1837                SetVariable setvar3,disable=0
1838               
1839                //
1840                RemoveFromGraph/W=ManualFitPanel#G0 chi2_map
1841               
1842//              Display/W=(259,23,643,346)/HOST=#
1843                AppendImage/W=ManualFitPanel#G0 chi2D
1844                SetActiveSubwindow ManualFitPanel#G0
1845                ModifyImage chi2D ctab= {*,*,ColdWarm,0}
1846                Label left "par"
1847                Label bottom "par2"
1848                SetActiveSubwindow ##
1849               
1850        else
1851                SetVariable setvar0,disable=0
1852                SetVariable setvar3,disable=2
1853               
1854                //
1855                RemoveImage/W=ManualFitPanel#G0 chi2D
1856
1857                AppendToGraph/W=ManualFitPanel#G0 root:chi2_map vs root:testVals
1858                SetActiveSubwindow ManualFitPanel#G0
1859//              Display/W=(259,23,643,346)/HOST=# root:chi2_map vs root:testVals
1860                ModifyGraph mode=4,msize=1,rgb=(65535,0,0)
1861                ModifyGraph tick=2,mirror=1
1862                Label left "Chi-squared"
1863        //      Label bottom "degrees" 
1864                SetActiveSubwindow ##
1865               
1866               
1867        endif
1868       
1869        return(0)
1870End
1871
1872
1873Function getParamFromWrapper()
1874
1875        Variable parNum
1876       
1877        GetSelection table, WrapperPanel#T0, 1
1878        parNum = V_startRow
1879        return(parNum)
1880End
1881
1882
1883Function VaryPCTButton(ctrlName) : ButtonControl
1884        String ctrlName
1885
1886        Variable percent
1887        strswitch(ctrlName)     // string switch
1888                case "button0":         
1889                        percent = 105
1890                        break
1891                case "button1":         
1892                        percent = 25
1893                        break
1894                case "button2":         
1895                        percent = 5
1896                        break           
1897                case "button3":         
1898                        percent = 1
1899                        break
1900                default:                                                       
1901                        percent = 10                                   
1902        endswitch
1903
1904        ControlInfo check0
1905        Variable isChecked = V_Value
1906
1907        // get the necessary info about parameters, etc.
1908        String folderStr,funcStr,coefStr
1909        Variable useCursors,useResol=0,pt1,pt2,minIndex
1910       
1911        ControlInfo/W=WrapperPanel popup_0
1912        folderStr=S_Value
1913       
1914        ControlInfo/W=WrapperPanel popup_1
1915        funcStr=S_Value
1916       
1917        ControlInfo/W=WrapperPanel popup_2
1918        coefStr=S_Value
1919       
1920//      ControlInfo/W=WrapperPanel check_0
1921//      useCursors=V_Value
1922//     
1923       
1924// first, figure out where we are...
1925        String suffix=getModelSuffix(funcStr)
1926       
1927        SetDataFolder $("root:"+folderStr)
1928        if(!exists(coefStr))
1929                // must be unsmeared model, work in the root folder
1930                SetDataFolder root:                             
1931                if(!exists(coefStr))            //this should be fine if the coef filter is working, but check anyhow
1932                        DoAlert 0,"the coefficient and data sets do not match"
1933                        return 0
1934                endif
1935        endif
1936               
1937        WAVE cw=$(coefStr)
1938        SetDataFolder root:
1939
1940       
1941        Variable loLim,hiLim,minChiSq
1942
1943        NVAR numStep = root:gNumManualSteps
1944        make/o/n=(numStep)/D root:testVals
1945        Wave testVals = root:testVals
1946        WAVE chi2_map = root:chi2_map
1947        Make/O/D/N=(numStep,numStep) root:chi2D
1948        WAVE chi2D = root:chi2D
1949       
1950       
1951        // then do either a 1D or 2D map of the chi squared
1952        if(isChecked)
1953       
1954                NVAR par = root:gNumManualParam
1955                NVAR par2 = root:gNumManualParam2
1956               
1957                Variable ii,jj,saveVal2
1958                saveVal2 = cw[par2]             //initial value of par2
1959               
1960                //steps in par2 direction
1961                make/o/n=(numStep)/D root:testVals2
1962                Wave testVals2 = root:testVals2
1963                loLim = cw[par2] - percent*cw[par2]/100
1964                hiLim = cw[par2] + percent*cw[par2]/100
1965                testVals2 = loLim + x*(hiLim-loLim)/numStep
1966
1967                SetScale/I x LoLim,HiLim,"", chi2D
1968
1969                //steps in par1 direction
1970                if(cw[par] != 0)       
1971                        loLim = cw[par] - percent*cw[par]/100
1972                        hiLim = cw[par] + percent*cw[par]/100
1973                else
1974                        loLim = -1
1975                        hiLim = 1
1976                endif
1977                testVals = loLim + x*(hiLim-loLim)/numStep
1978                SetScale/I y LoLim,HiLim,"", chi2D
1979
1980               
1981                for(ii=0;ii<numStep;ii+=1)
1982                        cw[par2] = testVals2[ii]                //set the value for par2, vary par
1983               
1984                        fChiMap_new(par,percent,cw,testVals)            //the wave chi2_map is generated
1985
1986                        chi2D[ii][] = chi2_map[q]
1987       
1988                endfor
1989
1990                // set the new minimum value
1991                WaveStats/Q chi2D
1992        // now with scaled dimensions of Chi2D, the reported values are the values, not the point index
1993                cw[par] = V_MinColLoc
1994                cw[par2] = V_MinRowLoc 
1995       
1996                // the minimum chi_squared  along this path is at: -- is it better?
1997                minChiSq = V_Min
1998       
1999                NVAR curChi2=root:gCurrentChiSq
2000                curChi2 = minChiSq     
2001       
2002                //V_min*1.01 = the 1% neighborhood around the solution
2003                ModifyImage/W=ManualFitPanel#G0 chi2D ctab= {(V_min*1.01),*,ColdWarm,0}
2004                ModifyImage/W=ManualFitPanel#G0 chi2D minRGB=(0,65535,0),maxRGB=(0,65535,0)
2005       
2006        else
2007                NVAR par = root:gNumManualParam
2008                par = getParamFromWrapper()
2009               
2010                if(cw[par] != 0)       
2011                        loLim = cw[par] - percent*cw[par]/100
2012                        hiLim = cw[par] + percent*cw[par]/100
2013                else
2014                        loLim = -1
2015                        hiLim = 1
2016                endif
2017                testVals = loLim + x*(hiLim-loLim)/numStep
2018
2019               
2020                fChiMap_new(par,percent,cw,testVals)            //the wave chi2_map is generated
2021                       
2022                // set the new minimum value
2023                WaveStats/Q chi2_map
2024                minIndex = V_minRowLoc
2025                cw[par] = testVals[minIndex]
2026               
2027                // the minimum chi_squared  along this path is at: -- is it better?
2028                minChiSq = chi2_map[minIndex]
2029       
2030                NVAR curChi2=root:gCurrentChiSq
2031                curChi2 = minChiSq
2032        endif
2033       
2034       
2035        return(0)
2036End
2037
2038
2039Proc mMapChiSquared_Pct(paramNum,percent)
2040        Variable paramNum=0,percent=50
2041        Prompt paramNum, "Enter parameter number: "
2042        Prompt percent, "Enter percent variation:"
2043
2044        fChiMap_new(paramNum,percent)
2045End
2046
2047//Macro mMapChiSquared(paramNum,loLim,hiLim)
2048//      Variable paramNum=0,loLim=0,hiLim=1
2049//      Prompt paramNum, "Enter parameter number: "
2050//      Prompt loLim, "Enter lower value:"
2051//      Prompt hiLim, "Enter higher value:"
2052//
2053//      fChiMap_new(paramNum,loLim,hiLim)
2054//End
2055
2056
2057// this does the setup
2058Function fChiMap_new(paramNum,percent,cw,testVals)
2059        Variable paramNum,percent
2060        Wave cw,testVals
2061       
2062//Function fChiMap_new(paramNum,percent)
2063//      Variable paramNum,percent
2064
2065
2066        String folderStr,funcStr,coefStr
2067        Variable useCursors,useResol=0,pt1,pt2,minIndex
2068       
2069        ControlInfo/W=WrapperPanel popup_0
2070        folderStr=S_Value
2071       
2072        ControlInfo/W=WrapperPanel popup_1
2073        funcStr=S_Value
2074       
2075        ControlInfo/W=WrapperPanel popup_2
2076        coefStr=S_Value
2077       
2078        ControlInfo/W=WrapperPanel check_0
2079        useCursors=V_Value
2080       
2081// coefficent wave cw is passed in
2082
2083// test for smeared function
2084        if(stringmatch(funcStr, "Smear*"))              // if it's a smeared function, need a struct
2085                useResol=1
2086        endif
2087       
2088        // wave references for the data (to pass)
2089        String DF="root:"+folderStr+":"
2090       
2091        WAVE yw=$(DF+folderStr+"_i")
2092        WAVE xw=$(DF+folderStr+"_q")
2093        WAVE sw=$(DF+folderStr+"_s")
2094
2095        if(useCursors)
2096                if(pcsr(A) > pcsr(B))
2097                        pt1 = pcsr(B)
2098                        pt2 = pcsr(A)
2099                else
2100                        pt1 = pcsr(A)
2101                        pt2 = pcsr(B)
2102                endif
2103        else
2104                //if cursors are not being used, find the first and last points of the data set, and pass them
2105                pt1 = 0
2106                pt2 = numpnts(yw)-1
2107        endif
2108
2109        Variable loLim,hiLim,minChiSq
2110
2111        SetDataFolder root:
2112       
2113        NVAR numStep = root:gNumManualSteps
2114        make/o/n=(numStep)/D root:chi2_map
2115        Wave chi2_map = root:chi2_map
2116//      Wave testVals = root:testVals
2117       
2118        //the testVals are genereated and passed by the calling routine
2119                       
2120        minIndex = chi2gen_new(funcStr,folderStr,xw,yw,sw,cw,paramNum,pt1,pt2,useResol,chi2_map,testVals)
2121       
2122        return(0)
2123End
2124
2125
2126// this does the math for a single value of "whichParam"
2127Function chi2gen_new(funcStr,folderStr,xw,yw,sw,cw,whichParam,lhs,rhs,useResol,chi2_map,testVals)
2128        String funcStr,folderStr
2129        Wave xw,yw,sw,cw      //        x data, y data, error wave, and coefficient wave
2130        variable whichParam  //which of the parameters to you want to vary, how far from the original value do you want to search (%)
2131        variable lhs, rhs    //specify a region of interest in the data using a left hand side and right hand side.
2132        variable useResol               // =1 if smeared used
2133        Wave chi2_map,testVals
2134 
2135        variable originalvalue = cw[whichparam]
2136//      variable range = originalValue * searchArea/100
2137        variable ii,err,minIndex
2138 
2139        duplicate/o yw, :theoretical_data, :chi2_data
2140        Wave theoretical_data, chi2_data
2141 
2142        String DF="root:"+folderStr+":"
2143        String suffix=getModelSuffix(funcStr)
2144
2145        // fill a struct instance whether it is needed or not
2146        Struct ResSmearAAOStruct fs
2147        WAVE/Z resW = $(DF+folderStr+"_res")                    //these may not exist, if 3-column data is used
2148        WAVE/Z fs.resW =  resW
2149//              WAVE yw=$(DF+folderStr+"_i")                    //these are passed in
2150//              WAVE xw=$(DF+folderStr+"_q")
2151//              WAVE sw=$(DF+folderStr+"_s")
2152        Wave fs.coefW = cw
2153        Wave fs.yW = theoretical_data
2154        Wave fs.xW = xw
2155 
2156 
2157 
2158        for(ii=0 ; ii < numpnts(chi2_map) ; ii+=1)
2159                cw[whichparam] = testVals[ii]
2160 
2161                if(useResol)
2162                        FUNCREF SANSModelSTRUCT_proto func1=$funcStr
2163                        err = func1(fs)
2164                else
2165                        FUNCREF SANSModelAAO_proto func2=$funcStr
2166                        func2(cw,theoretical_data,xw)
2167                endif
2168               
2169                chi2_data = (yw-theoretical_data)^2
2170 
2171                chi2_data /= sw^2
2172
2173                Wavestats/q/R=[lhs, rhs] chi2_data
2174 
2175                chi2_map[ii] = V_avg * V_npnts
2176        endfor
2177 
2178        cw[whichparam] = originalvalue
2179
2180       
2181        WaveStats/Q chi2_map
2182        minIndex = V_minRowLoc
2183//      Print "minimum at: ", minIndex,chi2_map[minIndex]
2184       
2185        killwaves/z theoretical_data, chi2_data
2186        return(minIndex)
2187End
2188
2189//////////////////////////
Note: See TracBrowser for help on using the repository browser.