source: sans/Dev/trunk/NCNR_User_Procedures/Analysis/Packages/GlobalFit/SimpleGlobalFit_NCNR_v40.ipf @ 515

Last change on this file since 515 was 515, checked in by srkline, 13 years ago

A bunch of random changes:
-SASCALC - added the 2.5 cm aperture NG3/7g/polarizer back in, but made the 5 cm the default
-Some fiddling with 2D functionality to enable 2D resolution smearing. Still a work in progress
-Added two new model functions, and added them to the list.
-Changes to the wrapper for the new release to generate kw=val strings as needed for each function
and its coefficients and parameters. This behavior has been changed in the new release, so this
fix should keep old analysis experiments compatible with the new version.

File size: 17.1 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2
3
4// panel meant to make it easier to fit two data sets with a single model
5// typically (but not necessarily) U+S, resolution smeared
6//
7// Uses a lot of the functionality from the Wrapper Panel - so be careful
8// if the behavior of that panel changes - especially the popup menus
9//
10// currently unsupported:
11// mask
12// constraints
13// epsilon (used, set behind the scenes but is not user-settable)
14//
15// ** some of the other assumptions/behaviors are:
16// - if a global variable is held by one set, it is (must be) held for the other set
17//   even though I don't automatically check the other box
18// - global parameter values are set from SET A. values in set B are overwritten during
19//   the fit
20// - upon initialization of the coefficients, coef_A and coef_B are set to those from the
21//   first data set (A). So the appropriate model must be plotted for set A. It does not
22//   need to be plotted for set B, although if you fit the sets separately, each fit can
23//   be used as a good first guess for the global fitting by cut/pase into the table.
24// - reports are always generated and automatically saved. Beware overwriting.
25// - weighting waves are automatically selected, as usual, since I know the data sets
26// - both data sets should be on the top graph. The fit, when finished, will try to append
27//   the results of the fit on the top graph.
28//
29// SRK FEB 2009
30
31// these waves feed the WM NewGlobalFit package, and must have the proper
32// names, locations, *and* dimLabels to work properly. But then it can be run
33// through all of the same machinery.
34
35//      Make/O/T/N=(numDataSets) root:Packages:NewGlobalFit:NewGF_FitFuncNames = ""
36//      Wave/T FitFuncNames = root:Packages:NewGlobalFit:NewGF_FitFuncNames
37
38//Make/O/T/N=(numDataSets, 2) root:Packages:NewGlobalFit:NewGF_DataSetsList
39//      Wave/T DataSets = root:Packages:NewGlobalFit:NewGF_DataSetsList
40
41//      Make/N=(numDataSets, numLinkageCols)/O root:Packages:NewGlobalFit:NewGF_LinkageMatrix
42//      Wave LinkageMatrix = root:Packages:NewGlobalFit:NewGF_LinkageMatrix
43
44//      Make/O/D/N=(nRealCoefs, 3) root:Packages:NewGlobalFit:NewGF_CoefWave
45//      Wave coefWave = root:Packages:NewGlobalFit:NewGF_CoefWave
46//      SetDimLabel 1,1,Hold,coefWave
47//      SetDimLabel 1,2,Epsilon,coefWave
48//      Make/O/T/N=(nRealCoefs) root:Packages:NewGlobalFit:NewGF_CoefficientNames
49//      Wave/T CoefNames = root:Packages:NewGlobalFit:NewGF_CoefficientNames   
50
51//Wave/T/Z ConstraintWave = root:Packages:NewGlobalFit:GFUI_GlobalFitConstraintWave
52// or $""
53
54
55 
56Proc OpenSimpleGlobalFit()
57        Init_SimpleGlobalFit()
58End
59
60Menu "SANS Models"
61//      "Global Fit", InitGlobalFitPanel()
62        Submenu "Packages"
63                "Unload Simple Global Fit",  UnloadSimpleGlobalFit()
64        End
65end
66
67Function Init_SimpleGlobalFit()
68        //make sure that folders exist - this is the first initialization to be called
69        NewDataFolder/O root:Packages
70        NewDataFolder/O root:Packages:NewGlobalFit
71       
72        DoWindow/F SimpGFPanel
73        if(V_flag==0)
74                SetDataFolder root:Packages:NewGlobalFit
75                // create waves for the list box, or for the embedded table?
76                Make/O/T/N=(10,4) listW
77                Make/O/B/N=(10,4) selW
78                Make/O/T/N=4 titles
79                titles[0] = "Coef #"
80                titles[1] = "Global?"
81                titles[2] = "Hold for Set A?"
82                titles[3] = "Hold for Set B?"
83               
84                listW[][0] = num2str(p)
85                selW[][0] = 0
86                selW[][1] = 2^5         // column is a checkbox
87                selW[][2] = 2^5
88                selW[][3] = 2^5
89               
90                Execute "SimpGFPanel()"
91                setDataFolder root:
92        endif
93End
94
95Window SimpGFPanel() : Panel
96        PauseUpdate; Silent 1           // building window...
97        NewPanel/W=(689,526,1318,1035)/K=1/N=SimpGFPanel as "Simple Global Fit Setup"
98        ModifyPanel cbRGB=(65535,65534,49151)
99       
100        GroupBox grpBox_0,pos={18,11},size={310,129}
101
102        PopupMenu popup_0a,pos={30,21},size={218,20},title="Data Set A "
103        PopupMenu popup_0a,mode=1,value= #"W_DataSetPopupList()"
104        PopupMenu popup_0b,pos={30,49},size={218,20},title="Data Set B "
105        PopupMenu popup_0b,mode=1,value= #"W_DataSetPopupList()"
106        PopupMenu popup_1,pos={30,80},size={136,20},title="Function"
107        PopupMenu popup_1,mode=1,value= #"W_FunctionPopupList()"
108        PopupMenu popup_2,pos={30,110},size={123,20},title="Coefficients"
109        PopupMenu popup_2,mode=1,value= #"SGF_CoefPopupList()",proc=SGF_CoefPopMenuProc
110        ListBox list0,pos={355,195},size={260,288},listWave=root:Packages:NewGlobalFit:listW
111        ListBox list0 selWave=root:Packages:NewGlobalFit:selW,proc=SGF_ListBoxProc
112        ListBox list0 titleWave=root:Packages:NewGlobalFit:titles//,userColumnResize=1
113        ListBox list0 widths={30,50,80,80}
114       
115        Button button_0,pos={344,13},size={100,20},title="Do The Fit"
116        Button button_0 proc=SGF_DoFitButtonProc
117        Button button_1,pos={369,173},size={50,20},proc=SaveCheckStateButtonProc,title="Save"
118        Button button_2,pos={429,173},size={70,20},proc=RestoreCheckStateButtonProc,title="Restore"
119        Button button_3,pos={500,13},size={100,20},proc=SGFitHelpButtonProc,title="Help"
120       
121        Edit/W=(14,174,348,495)/HOST=#
122        ModifyTable format(Point)=1,width(Point)=34
123        RenameWindow #,T0
124        SetActiveSubwindow ##
125       
126EndMacro
127
128//open the Help file for the Simple Global Fit
129Function SGFitHelpButtonProc(ba) : ButtonControl
130        STRUCT WMButtonAction &ba
131
132        switch( ba.eventCode )
133                case 2: // mouse up
134                        // click code here
135                        DisplayHelpTopic/Z/K=1 "Simple Global Fit"
136                        if(V_flag !=0)
137                                DoAlert 0,"The Simple Global Fit Help file could not be found"
138                        endif
139                        break
140        endswitch
141
142        return 0
143End
144
145
146// save the state of the checkboxes
147Function SaveCheckStateButtonProc(ba) : ButtonControl
148        STRUCT WMButtonAction &ba
149
150        switch( ba.eventCode )
151                case 2: // mouse up
152                        // click code here
153                        Duplicate/O root:Packages:NewGlobalFit:selW, root:Packages:NewGlobalFit:selW_saved
154                        break
155        endswitch
156
157        return 0
158End
159
160//restore the state of the checkboxes if the number of rows is correct
161Function RestoreCheckStateButtonProc(ba) : ButtonControl
162        STRUCT WMButtonAction &ba
163
164        switch( ba.eventCode )
165                case 2: // mouse up
166                        // click code here
167                        Wave sw_cur = root:Packages:NewGlobalFit:selW
168                        Wave sw_sav = root:Packages:NewGlobalFit:selW_saved
169
170                        Variable num_cur,num_sav
171                        num_cur = DimSize(sw_cur,0)
172                        num_sav = DimSize(sw_sav,0)
173
174                        if(num_cur == num_sav)
175                                sw_cur = sw_sav
176                        endif
177                       
178                        break
179        endswitch
180
181        return 0
182End
183
184
185
186
187// show the appropriate coefficient waves
188//
189// also need to search the folder listed in "data set" popup
190// for smeared coefs
191//
192// - or - restrict the coefficient list based on the model function
193// - new way, filter the possible values based on the data folder and function
194Function/S SGF_CoefPopupList()
195
196        String notPlotted="Please plot the function"
197        ControlInfo/W=SimpGFPanel popup_1
198        String funcStr=S_Value
199        String coefStr=getFunctionCoef(funcStr)
200       
201        if(cmpstr(coefStr,"")==0)               //no correspondence in the KW string
202                return(notPlotted)
203        endif
204       
205       
206        //found a coefficient wave - only two places to look
207        // is it in the root folder?
208        if(exists("root:"+coefStr) != 0)
209                return(coefStr)
210        endif
211       
212        // is it in the data folder? (this only checks "a")
213        ControlInfo/W=SimpGFPanel popup_0a
214        String folderStr=S_Value
215        if(exists("root:"+folderStr+":"+coefStr) != 0)
216                return(coefStr)
217        endif
218
219        return(notPlotted)
220End
221
222Function SGF_CoefPopMenuProc(pa) : PopupMenuControl
223        STRUCT WMPopupAction &pa
224
225        switch( pa.eventCode )
226                case 2: // mouse up
227                        Variable popNum = pa.popNum
228                        String popStr = pa.popStr
229                       
230                        //////
231                        String suffix = getModelSuffix(popStr)
232                        ControlInfo/W=SimpGFPanel popup_0a
233                        String folderStr_a=S_Value
234                       
235                        ControlInfo/W=SimpGFPanel popup_0b
236                        String folderStr_b=S_Value
237                       
238                        ControlInfo/W=SimpGFPanel popup_1
239                        String funcStr=S_Value
240                       
241                        if(cmpstr(popStr,"Please plot the function")==0)
242//                              Print "function not plotted"
243                                return(0)
244                        endif
245
246// this if/else/endif should not ever return an error alert     
247// it should simply set the data folder properly
248//
249// !! works only with folder/set A     
250                        if(DataFolderExists("root:"+folderStr_a))
251                                SetDataFolder $("root:"+folderStr_a)
252                                if(!exists(popStr))
253                                        // must be unsmeared model, work in the root folder
254                                        SetDataFolder root:                             
255                                        if(!exists(popStr))             //this should be fine if the coef filter is working, but check anyhow
256                                                DoAlert 0,"the coefficient and data sets do not match (1)"
257                                                return 0
258                                        endif
259                                endif
260                        else
261                                // must be unsmeared model, work in the root folder
262                                SetDataFolder root:     
263                                if(!exists(popStr))             //this should be fine if the coef filter is working, but check anyhow
264                                        DoAlert 0,"the coefficient and data sets do not match (2)"
265                                        return 0
266                                endif
267                        endif
268//                     
269                        // farm the work out to another function?
270                        Variable num=numpnts($popStr)
271                        // make the necessary waves, overwriting anything that exists?
272                       
273// duplicate the coefficient waves, A/B
274                        Duplicate/O $(popStr) root:Packages:NewGlobalFit:coef_A,root:Packages:NewGlobalFit:coef_B
275                        Wave coef_A = root:Packages:NewGlobalFit:coef_A
276                        Wave coef_B = root:Packages:NewGlobalFit:coef_B
277                       
278                        if(exists("Hold_"+suffix) == 0)
279                                Make/O/D/N=(num) $("epsilon_"+suffix),$("Hold_"+suffix)
280                                Make/O/T/N=(num) $("LoLim_"+suffix),$("HiLim_"+suffix)
281                                Wave eps = $("epsilon_"+suffix)
282                                Wave coef=$popStr
283                                if(eps[0] == 0)         //if eps already if filled, don't change it
284                                        eps = abs(coef*1e-4) + 1e-10                    //default eps is proportional to the coefficients
285                                endif
286                        endif
287                        // default epsilon values, sometimes needed for the fit
288                       
289                        WAVE/T LoLim = $("LoLim_"+suffix)
290                        WAVE/T HiLim = $("HiLim_"+suffix)
291                       
292                        // clear the table (a subwindow)
293                        DoWindow/F SimpGFPanel                          // ?? had to add this in during all of the cursor meddling...
294                        KillWindow SimpGFPanel#T0
295                        Edit/W=(14,174,348,495)/HOST=SimpGFPanel
296                        RenameWindow #,T0
297                        // get them onto the table
298                        // how do I get the parameter name?
299                        String param = getFunctionParams(funcStr)               //this is *hopefully* one wave
300                        AppendtoTable/W=SimpGFPanel#T0 $param
301                        AppendToTable/W=SimpGFPanel#T0 coef_A,coef_B
302//                      AppendToTable/W=SimpGFPanel#T0 $("Hold_"+suffix),$("LoLim_"+suffix),$("HiLim_"+suffix),$("epsilon_"+suffix)
303                        ModifyTable/W=SimpGFPanel#T0 width(Point)=34
304                       
305                        SetDataFolder root:
306                       
307// resize the list boxes based on the number of coefficients                   
308                        WAVE/T lw=root:Packages:NewGlobalFit:listW
309                        WAVE sw=root:Packages:NewGlobalFit:selW
310                        Redimension/N=(num,4) lw
311                        Redimension/N=(num,4) sw
312                        lw[][0] = num2str(p)
313                        sw[][0] = 0
314                        sw[][1] = 2^5           // column is a checkbox
315                        sw[][2] = 2^5
316                        sw[][3] = 2^5
317                        ///////
318                       
319                       
320                        break
321        endswitch
322
323        return 0
324End
325
326// tricky logic here - to make sure that selections are all in-sync and the coefficients too.
327//
328// maybe better to not do anything here, just update states after parsing the details of the selections
329//
330// bit 4 (0x10) is checkbox state
331Function SGF_ListBoxProc(lba) : ListBoxControl
332        STRUCT WMListboxAction &lba
333
334        Variable row = lba.row
335        Variable col = lba.col
336        WAVE/T/Z listWave = lba.listWave
337        WAVE/Z selWave = lba.selWave
338
339        //Print "event code = ",lba.eventCode
340
341        switch( lba.eventCode )
342                case -1: // control being killed
343                        break
344                case 1: //mouse down
345                        //if( (selWave[row][col] & 0x10) != 0)                  //test here is BEFORE the state changes
346                        //      Print "row,col is checked ",row,col
347                        //endif
348                        break
349                case 3: // double click
350                        break
351                case 4: // cell selection
352                case 5: // cell selection plus shift key
353                        break
354                case 6: // begin edit
355                        break
356                case 7: // finish edit
357                        break
358        endswitch
359
360        return 0
361End
362
363// first, it must parse everything for "OK-ness"
364// then construct the waves that GlobalFit needs
365// then dispatch
366// then do something with the results
367//
368Function SGF_DoFitButtonProc(ba) : ButtonControl
369        STRUCT WMButtonAction &ba
370
371        variable err=0
372        switch( ba.eventCode )
373                case 2: // mouse up
374                        // parse
375                        err = ParseSGFPanel()
376                        if(err)
377                                Print "Parse Error"
378                                break
379                        endif
380                       
381                        //wave construct (Waves exist if no parse errors)
382                        WAVE/T FitFuncNames = root:Packages:NewGlobalFit:NewGF_FitFuncNames
383                        Wave/T DataSets = root:Packages:NewGlobalFit:NewGF_DataSetsList
384                        Wave CoefDataSetLinkage = root:Packages:NewGlobalFit:NewGF_LinkageMatrix
385                        WAVE CoefWave = root:Packages:NewGlobalFit:NewGF_CoefWave
386                       
387                        //dispatch
388                        Variable options=105            //=64+32+16+1
389                        Variable FitCurvePoints = 200
390                        Variable DoAlertsOnError = 1
391                       
392                        err = DoNewGlobalFit(FitFuncNames, DataSets, CoefDataSetLinkage, CoefWave, $"", $"", Options, FitCurvePoints, DoAlertsOnError)
393                        //post-process results
394                        //Print "err = ",err
395                        // put results back into coef_a and coef_b
396                        UpdateSGFCoefs(CoefWave)
397                                               
398                        break
399        endswitch
400
401        return 0
402End
403
404// parse the panel and generate the necessary waves
405//
406Function ParseSGFPanel()
407
408        Variable err=0
409        SetDataFolder root:Packages:NewGlobalFit
410       
411//////Fitfunc names
412        ControlInfo/W=SimpGFPanel popup_1
413        String funcStr=S_Value
414        Make/O/T/N=1 NewGF_FitFuncNames
415        WAVE/T FitFuncNames = NewGF_FitFuncNames
416        FitFuncNames[0] = funcStr
417       
418////// data sets
419        ControlInfo/W=SimpGFPanel popup_2
420        String popStr=S_Value
421        String suffix = getModelSuffix(popStr)
422
423       
424        ControlInfo/W=SimpGFPanel popup_0a
425        String folderStr_a=S_Value
426       
427        ControlInfo/W=SimpGFPanel popup_0b
428        String folderStr_b=S_Value
429        Make/O/T/N=(2,4) NewGF_DataSetsList
430        Wave/T DataSets = NewGF_DataSetsList
431        // full paths to the waves
432        DataSets[0][0] = "root:"+folderStr_a+":"+folderStr_a + "_i"
433        DataSets[1][0] = "root:"+folderStr_b+":"+folderStr_b + "_i"
434        DataSets[0][1] = "root:"+folderStr_a+":"+folderStr_a + "_q"
435        DataSets[1][1] = "root:"+folderStr_b+":"+folderStr_b + "_q"
436        DataSets[0][2] = "root:"+folderStr_a+":"+folderStr_a + "_s"
437        DataSets[1][2] = "root:"+folderStr_b+":"+folderStr_b + "_s"
438        SetDimLabel 1, 2, Weights, DataSets
439// column [3] is the mask wave, not supported here
440        DataSets[0][3] = ""
441        DataSets[1][3] = ""
442       
443////// coefficient linkage matrix
444        Wave coef_A = coef_A
445        Wave coef_b = coef_b
446        Variable nc = numpnts(coef_A)
447       
448        Make/O/D/N=(2,nc+4) NewGF_LinkageMatrix
449        Wave CoefDataSetLinkage = NewGF_LinkageMatrix
450
451        WAVE selW = selW
452        Variable nRealCoefs = 0         // accumulates the number of independent coefficients (that is, non-link coefficients)
453        Variable ii,jj,numDataSets=2
454       
455        CoefDataSetLinkage[0][0] = 0            //function number, same for both
456        CoefDataSetLinkage[1][0] = 0
457        CoefDataSetLinkage[0][1] = 0            //first/last data pt numbers, set to zero on input
458        CoefDataSetLinkage[1][1] = 0            //first/last data pt numbers, set to zero on input
459        CoefDataSetLinkage[0][2] = 0            //first/last data pt numbers, set to zero on input
460        CoefDataSetLinkage[1][2] = 0            //first/last data pt numbers, set to zero on input
461        CoefDataSetLinkage[0][3] = nc           //number of coefficients
462        CoefDataSetLinkage[1][3] = nc           //number of coefficients
463       
464        //loop through coefs for first data set [0][]
465        // ! everything hits here - all coefficients are used...
466        Variable offset=4
467        for(ii=0;ii < nc; ii+=1)
468                CoefDataSetLinkage[0][ii+offset] = ii           
469        endfor
470        nRealCoefs = nc
471        // now 2nd data set may have some links
472        for(ii=0;ii < nc; ii+=1)
473                if (selW[ii][1] & 0x10)         //global coefficient
474                        CoefDataSetLinkage[1][ii+offset] = ii
475                else
476                        CoefDataSetLinkage[1][ii+offset] = nRealCoefs
477                        nRealCoefs +=1
478                endif
479        endfor
480       
481//// Cumulative coefficient wave and coefficient names
482// coefficient wave also contains hold[][1] and epsilon[][2]
483// do nothing with epsilon right now
484
485        Make/O/T/N=(nRealCoefs) NewGF_CoefficientNames=""
486        Make/O/D/N=(nRealCoefs,3) NewGF_CoefWave=0
487        Wave coefWave = NewGF_CoefWave
488        Wave/T CoefNames = NewGF_CoefficientNames
489        SetDimLabel 1,1,Hold,coefWave
490//      SetDimLabel 1,2,Epsilon,coefWave
491
492       
493//      String param = WaveList("*parameters_"+suffix, "", "TEXT:1," )          //this is *hopefully* one wave
494//      print "Param = ",param
495       
496        // take the global values from the coef_A wave
497        for(ii=0;ii < nc; ii+=1)
498                CoefWave[ii][0] = coef_a[ii]
499                if(selW[ii][2] & 0x10)          //held
500                        coefWave[ii][1] = 1
501                endif
502//              CoefNames[ii] =                 
503        endfor
504        // now 2nd data set may have some links
505        for(ii=0;ii < nc; ii+=1)
506                if (coefDataSetLinkage[0][ii+offset] == CoefDataSetLinkage[1][ii+offset])               //global coefficient
507                        //do nothing to set the coefficients
508                else
509                        CoefWave[CoefDataSetLinkage[1][ii+offset]][0] = coef_b[ii]                      //take non-global value from b
510                endif
511                if(selW[ii][3] & 0x10)          //global held, "b" checked
512                        coefWave[CoefDataSetLinkage[1][ii+offset]][1] = 1
513                endif
514        endfor
515
516//// constraint wave is not currently supported
517
518
519//// that's all of the waves
520
521        setDataFolder root:
522       
523        return(err)
524end
525
526Function UpdateSGFCoefs(CoefWave)
527        Wave CoefWave
528       
529        SetDataFolder root:Packages:NewGlobalFit
530        Wave coef_a=coef_a
531        Wave coef_b=coef_b
532        Variable nc = numpnts(coef_A)
533        Variable nTotal = DimSize(CoefWave, 0)
534       
535        Wave CoefDataSetLinkage=NewGF_LinkageMatrix
536        //loop through coefs for first data set [0][]
537        // ! everything hits here - all coefficients are used...
538        Variable ii,offset=4,index
539        for(ii=0;ii < nc; ii+=1)
540                coef_a[ii] = CoefWave[ii][0]   
541        endfor
542        // now 2nd data set may have some duplicates from globals
543        for(ii=0;ii < nc; ii+=1)
544                index = CoefDataSetLinkage[1][ii+offset]
545                coef_b[ii] = coefWave[index][0]
546        endfor
547       
548        SetDataFolder root:
549        return(0)
550End
551
552// clean up after itself, don't kill any data folder
553Function UnloadSimpleGlobalFit()
554        if (WinType("SimpGFPanel") == 7)
555                DoWindow/K SimpGFPanel
556        endif
557        if (WinType("GlobalFitGraph") != 0)
558                DoWindow/K GlobalFitGraph
559        endif
560
561        SVAR fileVerExt=root:Packages:NIST:SANS_ANA_EXTENSION
562        String fname="SimpleGlobalFit_NCNR"
563        Execute/P "DELETEINCLUDE \""+fname+fileVerExt+"\""
564        Execute/P "COMPILEPROCEDURES "
565        KillWaves/Z root:Packages:NewGlobalFit:listW
566        KillWaves/Z root:Packages:NewGlobalFit:selW
567        KillWaves/Z root:Packages:NewGlobalFit:titles
568       
569//      KillDataFolder/Z root:Packages:NewGlobalFit
570       
571       
572end
Note: See TracBrowser for help on using the repository browser.