source: sans/Analysis/branches/ajj_23APR07/IGOR_Package_Files/Put in User Procedures/SANS_Models_v3.00/Packages/GlobalFit/GlobalFit2_NCNR.ipf @ 223

Last change on this file since 223 was 223, checked in by srkline, 15 years ago

Globalfit now adds the correct graph to the report whether or not the progress graph is displayed.

Wrapper now has a button for feedback, position to be determined later.

File size: 160.5 KB
Line 
1#pragma rtGlobals=2             // Use modern global access method.
2#pragma version = 1.11
3#pragma IgorVersion = 6.0
4#pragma ModuleName= WM_NewGlobalFit1
5
6#include <BringDestToFront>
7#include <SaveRestoreWindowCoords>
8
9//**************************************
10// Changes in Global Fit procedures
11//
12//      1.00    first release of Global Fit 2. Adds multi-function capability and ability to link fit coefficients
13//                      in arbitrary groups. Thus, a coefficient that is not linked to any other coefficient is a "local"
14//                      coefficient. A coefficient that has all instances linked together is global. This is what the original
15//                      Global Fit package allowed. In addition, Global Fit 2 allows you to link coefficients into groups that
16//                      span different fitting functions, or include just a subset of instances of a coefficient.
17//
18//      1.01    Fixed bugs in contextual menu that pops up from the Initial Guess title cell in the coefficient list
19//                              on the Coefficient Control tab.
20//                      Now handles NaN's in data sets, mask waves and weight waves
21//
22//      1.02    Now uses global string variable for hold string to avoid making the command too long.
23//
24//      1.03    Cleaned up contextual menus a bit. Click in Data Sets and Functions list requires Control key to present menu.
25//                      Coefficient list on Coefficient Control tab has items that read "... Selection to(from) wave..." when a selection is present.
26//
27//      1.04    Fixed bug: On Windows, if the Global Fit panel was minimized, it gave an error when the window resize code tried to
28//                      arrange the controls in a too-small window.
29//
30//      1.05    Fixed bugs:
31//                              Mask wave panel didn't get full paths for Y waves, so it didn't work correctly when Y waves were
32//                              not in root:
33//
34//                              Coefficient Control list didn't update when Y waves were replaced using the Set Y Wave menu.
35//
36//  1.06        If the Global Fit control panel was re-sized very large to see lots of coefficients, the coefficient control
37//                              tab could be seen at the right edge.
38//
39//                      Waves named "fit_<data set name>" were created but not used. They are no longer made.
40//
41//      1.07    Fixed a bug in NewGF_SetCoefsFromWaveProc that caused problems with the Set from Wave menu.
42//      1.08    Fixed a bug in NewGF_CoefRowForLink() that caused problems connected linked cells on the Coefficient
43//                              Control tab.
44//      1.09    Added option for log-spaced X axis for destination waves.
45//      1.10    Fixed the bug caused by the fix at 1.08. Had to create a new function: NewGF_CoefListRowForLink();
46//                      NewGF_CoefRowForLink() was being used for two different but related purposes.
47
48//      1.11    SRK - changes to require Igor 6.0 and to use structure fit functions that are specific to resolution smearing of
49//                      NCNR SANS and USANS data sets. These changes are marked with //SRK comments
50
51//
52//**************************************
53
54//**************************************
55// Things to add in the future:
56//
57//              Want something? Tell support@wavemetrics.com about it!
58//**************************************
59
60//SRK
61//Menu "Analysis"
62//      "Global Fit", WM_NewGlobalFit1#InitNewGlobalFitPanel()
63//      "Unload Global Fit", WM_NewGlobalFit1#UnloadNewGlobalFit()
64//end
65Menu "Macros"
66//      "Global Fit", InitGlobalFitPanel()
67        Submenu "Packages"
68                "Unload Global Fit",  WM_NewGlobalFit1#UnloadNewGlobalFit()
69        End
70end
71//eSRK
72
73// This is the prototype function for the user's fit function
74// If you create your fitting function using the New Fit Function button in the Curve Fitting dialog,
75// it will have the FitFunc keyword, and that will make it show up in the menu in the Global Fit control panel.
76Function GFFitFuncTemplate(w, xx) : FitFunc
77        Wave w
78        Variable xx
79       
80        DoAlert 0, "Global Fit is running the template normal fitting function for some reason."
81        return nan
82end
83
84Function GFFitAllAtOnceTemplate(pw, yw, xw) : FitFunc
85        Wave pw, yw, xw
86       
87        DoAlert 0, "Global Fit is running the AAO template fitting function for some reason."
88        yw = nan
89        return nan
90end
91
92//SRK - added new template for AAO structure fit function type
93Function GFFitAAOStructTemplate(s) : FitFunc
94        Struct ResSmearAAOStruct &s
95       
96        DoAlert 0, "Global Fit is running the STRUCT template fitting function for some reason."
97        s.yw = nan
98        return nan
99end
100//eSRK
101
102static constant FuncPointerCol = 0
103static constant FirstPointCol = 1
104static constant LastPointCol = 2
105static constant NumFuncCoefsCol = 3
106static constant FirstCoefCol = 4
107
108Function NewGlblFitFunc(inpw, inyw, inxw)
109        Wave inpw, inyw, inxw
110
111        Wave Xw = root:Packages:NewGlobalFit:XCumData
112        Wave DataSetPointer = root:Packages:NewGlobalFit:DataSetPointer
113       
114        Wave CoefDataSetLinkage = root:Packages:NewGlobalFit:CoefDataSetLinkage
115        Wave/T FitFuncList = root:Packages:NewGlobalFit:FitFuncList
116        Wave SC=root:Packages:NewGlobalFit:ScratchCoefs
117       
118        Variable numSets = DimSize(CoefDataSetLinkage, 0)
119        Variable CoefDataSetLinkageIndex, i     
120       
121        for (i = 0; i < NumSets; i += 1)
122                Variable firstP = CoefDataSetLinkage[i][FirstPointCol]
123                Variable lastP = CoefDataSetLinkage[i][LastPointCol]
124
125                CoefDataSetLinkageIndex = DataSetPointer[firstP]
126                FUNCREF GFFitFuncTemplate theFitFunc = $(FitFuncList[CoefDataSetLinkage[CoefDataSetLinkageIndex][FuncPointerCol]])
127
128                SC = inpw[CoefDataSetLinkage[CoefDataSetLinkageIndex][FirstCoefCol+p]]
129                inyw[firstP, lastP] = theFitFunc(SC, Xw[p])
130        endfor
131end
132
133Function NewGlblFitFuncAllAtOnce(inpw, inyw, inxw)
134        Wave inpw, inyw, inxw
135       
136        Wave DataSetPointer = root:Packages:NewGlobalFit:DataSetPointer
137       
138        Wave CoefDataSetLinkage = root:Packages:NewGlobalFit:CoefDataSetLinkage
139        Wave/T FitFuncList = root:Packages:NewGlobalFit:FitFuncList
140        Wave SC=root:Packages:NewGlobalFit:ScratchCoefs
141       
142        Variable CoefDataSetLinkageIndex, i
143       
144        Variable numSets = DimSize(CoefDataSetLinkage, 0)
145        for (i = 0; i < NumSets; i += 1)
146                Variable firstP = CoefDataSetLinkage[i][FirstPointCol]
147                Variable lastP = CoefDataSetLinkage[i][LastPointCol]
148
149                CoefDataSetLinkageIndex = DataSetPointer[firstP]
150                FUNCREF GFFitAllAtOnceTemplate theFitFunc = $(FitFuncList[CoefDataSetLinkage[CoefDataSetLinkageIndex][FuncPointerCol]])
151
152                SC = inpw[CoefDataSetLinkage[CoefDataSetLinkageIndex][FirstCoefCol+p]]
153       
154                Duplicate/O/R=[firstP,lastP] inxw, TempXW, TempYW
155                TempXW = inxw[p+firstP]
156                SC = inpw[CoefDataSetLinkage[i][p+FirstCoefCol]]
157                theFitFunc(SC, TempYW, TempXW)
158                inyw[firstP, lastP] = TempYW[p-firstP]
159        endfor
160end
161
162//SRK - added actual function for AAO structure fit function to be used during global fitting
163// does not pass in the structure, but rather creates it as needed based on the name of the data set
164// for each segment of the data to be fitted
165//
166// created by not-so-simple changes to NewGlblFitFuncAllAtOnce()
167//Function NewGlblFitFuncAAOStruct(inpw, inyw, inxw)
168//      Wave inpw, inyw, inxw
169Function NewGlblFitFuncAAOStruct(s)
170        Struct ResSmearAAOStruct &s
171       
172        WAVE inpw=s.coefW                       //keep the same wave names for convenience
173        WAVE inyw=s.yW                  //may remove later if possible for speed
174        WAVE inxw=s.xW
175       
176        Wave DataSetPointer = root:Packages:NewGlobalFit:DataSetPointer
177       
178        Wave CoefDataSetLinkage = root:Packages:NewGlobalFit:CoefDataSetLinkage
179        Wave/T FitFuncList = root:Packages:NewGlobalFit:FitFuncList
180        Wave SC=root:Packages:NewGlobalFit:ScratchCoefs
181
182        Wave/T DataSets = root:Packages:NewGlobalFit:NewGF_DataSetsList
183        STRUCT ResSmearAAOStruct fs
184
185        Variable CoefDataSetLinkageIndex, i
186        Variable numSets = DimSize(CoefDataSetLinkage, 0)
187        Variable MaskCol = FindDimLabel(DataSets, 1, "Masks")
188        Variable pt1,pt2,newN
189
190        if(numsets==1)
191                i=0
192        endif
193       
194        for (i = 0; i < NumSets; i += 1)
195                Variable firstP = CoefDataSetLinkage[i][FirstPointCol]
196                Variable lastP = CoefDataSetLinkage[i][LastPointCol]
197
198                CoefDataSetLinkageIndex = DataSetPointer[firstP]
199                FUNCREF GFFitAAOStructTemplate theFitFunc = $(FitFuncList[CoefDataSetLinkage[CoefDataSetLinkageIndex][FuncPointerCol]])
200
201                String str=DataSets[CoefDataSetLinkageIndex][0]         //this seems to work
202                String DF=ParseFilePath(1, str, ":", 1, 0)
203
204                str=str[0,strlen(str)-3]                //remove the "_i" = DataFolder:name
205                WAVE resW = $(str+"_res")
206
207// when the data sets are concatenated, the res wave is NOT, so it needs to be properly done here, for either the matrix or the 4-col wave             
208//??            Wave/Z mw = $(DataSets[i][MaskCol])
209                Wave/Z mw = $(DataSets[CoefDataSetLinkageIndex][MaskCol])
210                ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_MaskingCheckBox
211                Variable useCursors = V_Value
212                if(useCursors)
213                        //find the first 1,  then find the zero
214                        pt1 = 0
215                        do
216                                if(mw[pt1]==1)
217                                        break
218                                endif
219                                pt1+=1
220                        while(pt1<numpnts(mw))
221                       
222                        pt2 = pt1
223                        do
224                                if(mw[pt2]==0)
225                                        break
226                                endif
227                                pt2+=1
228                        while(pt2<numpnts(mw))
229                        pt2 -= 1
230                       
231                        newN = pt2 - pt1 + 1            // +1 includes both cursors in the fit
232                        if((dimsize(resW,1) > 4))
233                                Make/O/D/N=(newN,newN) $(DF+"crsrResW")         //USANS nxn
234                                WAVE crsrResW = $(DF+"crsrResW")
235                                crsrResW = resW[p+pt1][q+pt1]
236                        else
237                                Make/O/D/N=(newN,4) $(DF+"crsrResW")                    //SANS nx4
238                                WAVE crsrResW = $(DF+"crsrResW")
239                                crsrResW = resW[p+pt1][q]
240                        endif
241                        //assign to the struct
242                        WAVE fs.resW =  crsrResW
243                else
244                //use all the data points, use the resW as is   
245                        WAVE fs.resW =  resW
246                endif
247               
248                //back to our normal program
249//SRK           SC = inpw[CoefDataSetLinkage[CoefDataSetLinkageIndex][FirstCoefCol+p]]
250       
251                Duplicate/O/R=[firstP,lastP] inxw, TempXW, TempYW
252                TempXW = inxw[p+firstP]
253                SC = inpw[CoefDataSetLinkage[i][p+FirstCoefCol]]
254
255                WAVE fs.coefW = SC              //is this the proper way to populate? seems redundant...
256                WAVE fs.yW = TempYW
257                WAVE fs.xW = TempXW
258               
259                theFitFunc(fs)          //this is a structure function too
260                //inyw[firstP, lastP] = TempYW[p-firstP]
261                s.yW[firstP, lastP] = TempYW[p-firstP]
262
263        endfor
264end
265//eSRK
266
267//---------------------------------------------
268//  Function that actually does a global fit, independent of the GUI
269//---------------------------------------------
270
271constant NewGlobalFitNO_DATASETS = -1
272constant NewGlobalFitBAD_FITFUNC = -2
273constant NewGlobalFitBAD_YWAVE = -3
274constant NewGlobalFitBAD_XWAVE = -4
275constant NewGlobalFitBAD_COEFINFO = -5
276constant NewGlobalFitNOWTWAVE = -6
277constant NewGlobalFitWTWAVEBADPOINTS = -7
278constant NewGlobalFitNOMSKWAVE = -8
279constant NewGlobalFitMSKWAVEBADPOINTS = -9
280constant NewGlobalFitXWaveBADPOINTS = -10
281
282static Function/S GF_DataSetErrorMessage(code, errorname)
283        Variable code
284        string errorname
285       
286        switch (code)
287                case NewGlobalFitNO_DATASETS:
288                        return "There are no data sets in the list of data sets."
289                        break
290                case NewGlobalFitBAD_YWAVE:
291                        return "The Y wave \""+errorname+"\" does not exist"
292                        break
293                case NewGlobalFitBAD_XWAVE:
294                        return "The X wave \""+errorname+"\" does not exist"
295                        break
296                case NewGlobalFitNOWTWAVE:
297                        return "The weight wave \""+errorname+"\" does not exist."
298                        break
299                case NewGlobalFitWTWAVEBADPOINTS:
300                        return "The weight wave \""+errorname+"\" has a different number of points than the corresponding data set wave."
301                        break
302                case NewGlobalFitNOMSKWAVE:
303                        return "The mask wave \""+errorname+"\" does not exist."
304                        break
305                case NewGlobalFitMSKWAVEBADPOINTS:
306                        return "The mask wave \""+errorname+"\" has a different number of points than the corresponding data set wave."
307                        break
308                case NewGlobalFitXWaveBADPOINTS:
309                        return "The X wave \""+errorname+"\" has a different number of points than the corresponding Y wave."
310                        break
311                default:
312                        return "Unknown problem with data sets. Error name: "+errorname
313        endswitch
314end
315
316constant NewGFOptionAPPEND_RESULTS = 1
317constant NewGFOptionCALC_RESIDS = 2
318constant NewGFOptionCOV_MATRIX = 4
319constant NewGFOptionFIT_GRAPH = 8
320constant NewGFOptionQUIET = 16
321constant NewGFOptionWTISSTD = 32
322constant NewGFOptionMAKE_FIT_WAVES = 64
323constant NewGFOptionCOR_MATRIX = 128
324constant NewGFOptionLOG_DEST_WAVE = 256
325
326Function DoNewGlobalFit(FitFuncNames, DataSets, CoefDataSetLinkage, CoefWave, CoefNames, ConstraintWave, Options, FitCurvePoints, DoAlertsOnError, [errorName])
327        Wave/T FitFuncNames             // a text wave containing a list of the fit functions to be used in this fit.
328
329        Wave/T DataSets                 // Wave containing a list of data sets.
330                                                                // Column 0 contains Y data sets.
331                                                                // Column 1 contains X data sets. Enter _calculated_ in a row if appropriate.
332                                                                // A column with label "Weights", if it exists, contains names of weighting waves for each dataset.
333                                                                // A column with label "Masks", if it exists, contains names of mask waves for each data set.
334
335        Wave CoefDataSetLinkage // a matrix wave with a row for each data set and N+2 columns, where N is the maximum number of coefficients
336                                                                // used by any of the fit functions. It looks like this for a hypothetical case of two functions and four
337                                                                // data sets:
338                                                               
339                                                                //              |       f()     first   last    N       c0      c1      c2      c3      c4      c5
340                                                                //      ---|-----------------------------
341                                                                //      ds1     |       0       0               100             5       0       1       2       3       4       -1
342                                                                //      ds2     |       0       101             150             5       5       6       2       7       4       -1
343                                                                //      ds3     |       1       151             220             6       8       9       2       10      11      12
344                                                                //      ds4     |       1       221             300             6       13      14      2       15      16      12
345
346                                                                // In this matrix, I imagine fitting to two functions, one of which takes 5 coefficients, the other 6.
347                                                                // Coefficients 0, 1, and 3 for function f1 are local- they have distinct coefficient array indices
348                                                                // everywhere. Coefficient 2 is global- the same coefficient array index is used for every data set.
349                                                                // Coefficient 4 is "shared local" (group global?)- it is global for ds1 and ds2. The corresponding
350                                                                // coefficient for ds3 and ds4 is local- it probably refers to something entirely different. Function
351                                                                // f1 has no coefficient 5- hence the -1. For f2, coefficient 5 is shared between the data sets (ds3
352                                                                // and ds4) which use f2. The column labelled N is the number of coefficients needed by the fit function.
353                                                                // The column labelled f() has an index into the FitFuncNames wave.
354                                                                // These columns are set up by the function in its private copy. You can set them to zero:
355                                                                // The column labelled first contains the point number where that data set starts in the cumulative waves.
356                                                                // The column labelled last contains the point number where the last point of that data set resides in the cumulative waves
357                                                               
358        Wave CoefWave                           // Wave containing initial guesses. The entries in the second and greater columns of the CoefDataSetLinkage
359                                                                // wave are indices into this wave.
360                                                               
361                                                                // There is no particular order- make sure the order here and the indices in CoefDataSetLinkage are consistent.
362                                                               
363                                                                // Column 0 contains initial guesses
364                                                                // A column with label "Hold", if it exists, specifies held coefficients
365                                                                // A column with label "Epsilon", if it exists, holds epsilon values for the coefficients
366                                                               
367        Wave/T/Z CoefNames              // optional text wave with same number of rows as CoefWave. Gives a name for referring to a particular
368                                                                // coefficient in coefWave. This is used only in reports to make them more readable. If you don't want to
369                                                                // use this wave, use $"" instead of wave name.
370
371        Wave/T/Z ConstraintWave // This constraint wave will be used straight as it comes, so K0, K1, etc. refer to the order of
372                                                                // coefficients as laid out in CoefWave.
373                                                                // If no constraints, use $"".
374
375        Variable Options                        // 1: Append Results to Top Graph (implies option 64).
376                                                                // 2: Calculate Residuals
377                                                                // 4: Covariance Matrix
378                                                                // 8: Do Fit Graph (a graph showing the actual fit in progress)
379                                                                // 16: Quiet- No printing in History
380                                                                // 32: Weight waves contain Standard Deviation (0 means 1/SD)
381                                                                // 64: Make fit curve waves (even if option 1 is not turned on)
382                                                                // 128: Correlation matrix (implies option 4)
383                                                                // 256: Result waves should have log spacing. Generates an GFitX_ wave to go with the GFit_ destination waves.
384
385        Variable FitCurvePoints // number of points for auto-destination waves
386
387        Variable DoAlertsOnError        // if 1, this function puts up alert boxes with messages about errors. These alert boxes
388                                                                        // may give more information than the error code returned from the function.
389
390        String &errorName                       // Wave name that was found to be in error. Only applies to certain errors.
391       
392
393        Variable i,j
394       
395        String saveDF = GetDataFolder(1)
396        SetDataFolder root:
397        NewDataFolder/O/S Packages
398        NewDataFolder/O NewGlobalFit
399        SetDataFolder $saveDF
400       
401        Variable err
402        Variable errorWaveRow, errorWaveColumn
403        String errorWaveName
404        Variable IsAllAtOnce
405
406// SRK -GF_FunctionType now returns 0 for regular, 1 for AAO, **2** for my struct (which is also AAO)
407// this will stop users from mixing smeared and unsmeared models
408//
409// also, check here for "Smeared" functions, to set the useRes flag
410//
411        IsAllAtOnce = GF_FunctionType(FitFuncNames[0])
412        for (i = 0; i < DimSize(FitFuncNames, 0); i += 1)
413                Variable functype = GF_FunctionType(FitFuncNames[i])
414                if (functype == GF_FuncType_BadFunc)
415                        if (DoAlertsOnError)
416                                DoAlert 0, "The function "+FitFuncNames[i]+" is not of the proper format."
417                                return -1
418                        endif
419                elseif (functype == GF_FuncType_NoFunc)
420                        if (DoAlertsOnError)
421                                DoAlert 0, "The function "+FitFuncNames[i]+" does not exist."
422                                return -1
423                        endif
424                endif
425                if (functype != IsAllAtOnce)
426                        if (DoAlertsOnError)
427                                DoAlert 0, "All your fit functions must be either regular fit functions or all-at-once functions. They cannot be mixed."
428                                return -1
429                        endif
430                endif
431        endfor
432        //now do my check, to make sure useRes is set correctly
433        Variable useRes=0,isSmearedFn=0
434        String testStr=FitFuncNames[0]
435        isSmearedFn =!(strsearch(testStr, "Smear", 0))          // == !0 == 1 if "Smear*" found at character 0
436        for (i = 0; i < DimSize(FitFuncNames, 0); i += 1)       
437                testStr=FitFuncNames[i]
438                if(!(strsearch(testStr, "Smear", 0)) != isSmearedFn)
439                        DoAlert 0,"You cannot mix Smeared and unsmeared fitting functions"
440                        return -1
441                endif
442        endfor
443        useRes=isSmearedFn
444//eSRK
445       
446        Duplicate/O CoefDataSetLinkage, root:Packages:NewGlobalFit:CoefDataSetLinkage
447        Wave privateLinkage = root:Packages:NewGlobalFit:CoefDataSetLinkage
448        Duplicate/O/T FitFuncNames, root:Packages:NewGlobalFit:FitFuncList
449       
450        Variable DoResid=0
451        Variable doWeighting=0
452        Variable doMasking=0
453       
454DoUpdate
455//
456        err = NewGF_CheckDSets_BuildCumWaves(DataSets, privateLinkage, doWeighting, doMasking, errorWaveName, errorWaveRow, errorWaveColumn)
457DoUpdate
458        if (err < 0)
459                if (err == NewGlobalFitNO_DATASETS)
460                        DoAlert 0, "There are no data sets in the list of data sets."
461                elseif (DoAlertsOnError)
462                        DoAlert 0, GF_DataSetErrorMessage(err, errorWaveName)
463                endif
464                if (!ParamIsDefault(errorName))
465                        errorName = errorWaveName
466                endif
467                return err
468        endif
469        Wave Xw = root:Packages:NewGlobalFit:XCumData
470        Wave Yw = root:Packages:NewGlobalFit:YCumData
471        Duplicate/O YW, root:Packages:NewGlobalFit:FitY
472        Wave FitY = root:Packages:NewGlobalFit:FitY
473        FitY = NaN
474       
475        Variable MaxFuncCoefs = 0
476        for (i = 0; i < DimSize(DataSets, 0); i += 1)
477                MaxFuncCoefs = max(MaxFuncCoefs, privateLinkage[i][NumFuncCoefsCol])
478        endfor
479        Make/O/D/N=(MaxFuncCoefs) root:Packages:NewGlobalFit:ScratchCoefs
480       
481        Make/D/O/N=(DimSize(CoefWave, 0)) root:Packages:NewGlobalFit:MasterCoefs       
482        Wave MasterCoefs = root:Packages:NewGlobalFit:MasterCoefs
483        MasterCoefs = CoefWave[p][0]
484       
485        if (!WaveExists(CoefNames))
486                Make/T/O/N=(DimSize(CoefWave, 0)) root:Packages:NewGlobalFit:CoefNames
487                Wave/T CoefNames = root:Packages:NewGlobalFit:CoefNames
488                // go through the matrix backwards so that the name we end up with refers to it's first use in the matrix
489                for (i = DimSize(privateLinkage, 0)-1; i >= 0 ; i -= 1)
490                        String fname = FitFuncNames[privateLinkage[i][FuncPointerCol]]
491                        for (j = DimSize(privateLinkage, 1)-1; j >= FirstCoefCol; j -= 1)
492                                if (privateLinkage[i][j] < 0)
493                                        continue
494                                endif
495                                CoefNames[privateLinkage[i][j]] = fname+":C"+num2istr(j-FirstCoefCol)
496                        endfor
497                endfor
498        endif
499       
500        String ResidString=""
501        String Command=""
502       
503        if (Options & NewGFOptionCALC_RESIDS)
504                DoResid = 1
505                ResidString="/R"
506        endif
507
508        if (options & NewGFOptionFIT_GRAPH)     
509                if (WinType("GlobalFitGraph") != 0)
510                        DoWindow/K GlobalFitGraph
511                endif
512                String SavedWindowCoords = WC_WindowCoordinatesGetStr("GlobalFitGraph", 0)
513                if (strlen(SavedWindowCoords) > 0)
514                        Execute "Display/W=("+SavedWindowCoords+") as \"Global Analysis Progress\""
515                else
516                        Display as "Global Analysis Progress"
517                endif
518                DoWindow/C GlobalFitGraph
519                ColorTab2Wave Rainbow
520                Wave M_colors
521                Duplicate/O M_colors, root:Packages:NewGlobalFit:NewGF_TraceColors
522                Wave colors = root:Packages:NewGlobalFit:NewGF_TraceColors
523                Variable index = 0, size = DimSize(M_colors, 0)
524                for (i = 0; i < size; i += 1)
525                        colors[i][] = M_colors[index][q]
526                        index += 37
527                        if (index >= size)
528                                index -= size
529                        endif
530                endfor
531                KillWaves/Z M_colors
532                Variable nTraces = DimSize(privateLinkage, 0)
533                for (i = 0; i < nTraces; i += 1)
534                        Variable start = privateLinkage[i][FirstPointCol]
535                        Variable theEnd = privateLinkage[i][LastPointCol]
536                        AppendToGraph Yw[start, theEnd] vs Xw[start, theEnd]
537                        AppendToGraph FitY[start, theEnd] vs Xw[start, theEnd]
538                endfor
539                DoUpdate
540                for (i = 0; i < nTraces; i += 1)
541                        ModifyGraph mode[2*i]=2
542                        ModifyGraph marker[2*i]=8
543                        ModifyGraph lSize[2*i]=2
544                        ModifyGraph rgb[2*i]=(colors[i][0],colors[i][1],colors[i][2])
545                        ModifyGraph rgb[2*i+1]=(colors[i][0],colors[i][1],colors[i][2])
546                endfor         
547                ModifyGraph gbRGB=(17476,17476,17476)
548                if (options & NewGFOptionLOG_DEST_WAVE)
549                        WaveStats/Q/M=1 xW
550                        if ( (V_min <= 0) || (V_max <= 0) )
551                                // bad x range for log- cancel the option
552                                options = options & ~NewGFOptionLOG_DEST_WAVE
553                        else
554                                // the progress graph should have log X axis
555                                ModifyGraph/W=GlobalFitGraph log(bottom)=1
556                        endif
557                endif
558                SetWindow GlobalFitGraph, hook = WC_WindowCoordinatesHook
559               
560                if (DoResid)
561                        Duplicate/O Yw, root:Packages:NewGlobalFit:NewGF_ResidY
562                        ResidString = "/R=NewGF_ResidY"
563                        Wave rw = root:Packages:NewGlobalFit:NewGF_ResidY
564                        for (i = 0; i < nTraces; i += 1)
565                                start = privateLinkage[i][FirstPointCol]
566                                theEnd = privateLinkage[i][LastPointCol]
567                                AppendToGraph/L=ResidLeftAxis rw[start, theEnd] vs Xw[start, theEnd]
568                        endfor
569                        DoUpdate
570                        for (i = 0; i < nTraces; i += 1)
571                                ModifyGraph mode[2*nTraces+i]=2
572                                ModifyGraph rgb[2*nTraces+i]=(colors[i][0],colors[i][1],colors[i][2])
573                                ModifyGraph lSize[2*nTraces+i]=2
574                        endfor
575                        ModifyGraph lblPos(ResidLeftAxis)=51
576                        ModifyGraph zero(ResidLeftAxis)=1
577                        ModifyGraph freePos(ResidLeftAxis)={0,kwFraction}
578                        ModifyGraph axisEnab(left)={0,0.78}
579                        ModifyGraph axisEnab(ResidLeftAxis)={0.82,1}
580                endif
581        endif
582       
583       
584        Duplicate/D/O MasterCoefs, root:Packages:NewGlobalFit:EpsilonWave
585        Wave EP = root:Packages:NewGlobalFit:EpsilonWave
586        Variable useEps=1               //SRK, always use epsilon, may want a better way to set these?
587        //Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
588        //CoefListWave[][4] = "1e-6"            // a reasonable value for epsilon
589        if (FindDimLabel(CoefWave, 1, "Epsilon") == -2)
590                EP = abs(MasterCoefs*1e-4) + 1e-10              //SRK
591                //EP = 1e-4
592        else
593                EP = abs(MasterCoefs*1e-4) + 1e-10              //SRK
594                //EP = abs(CoefWave[p][%Epsilon])               //SRK
595        endif
596
597        Variable quiet = ((Options & NewGFOptionQUIET) != 0)
598        if (!quiet)
599                Print "*** Doing Global fit ***"
600        endif
601       
602        if (Options & NewGFOptionCOR_MATRIX)
603                Options = Options | NewGFOptionCOV_MATRIX
604        endif
605       
606        String CovarianceString = ""
607        if (Options & NewGFOptionCOV_MATRIX)
608                CovarianceString="/M=2"
609        endif
610       
611DoUpdate
612        string funcName
613        //SRK - remove leading space from name strings since I am not building a command
614        switch(isAllAtOnce)
615                case 0:
616                        funcName = "NewGlblFitFunc"
617                        break
618                case 1:
619                        funcName = "NewGlblFitFuncAllAtOnce"
620                        break
621                case 2:
622                        funcName = "NewGlblFitFuncAAOStruct"
623                        STRUCT ResSmearAAOStruct sGF
624                        break
625                default:       
626                        Abort "is AAO switch has failed to match case"
627        endswitch
628//      if (isAllAtOnce==1)
629//              funcName = " NewGlblFitFuncAllAtOnce"
630//      else
631//              funcName = " NewGlblFitFunc"
632//      endif
633
634        //eSRK
635
636        Command =  "FuncFit"+CovarianceString+" "
637        if (quiet)
638                Command += "/Q"
639        endif
640        String/G root:Packages:NewGlobalFit:newGF_HoldString
641        SVAR newGF_HoldString = root:Packages:NewGlobalFit:newGF_HoldString
642        newGF_HoldString = MakeHoldString(CoefWave, quiet, 1)           // MakeHoldString() returns "" if there are no holds
643        if (strlen(newGF_HoldString) > 0)
644                Command += "/H=root:Packages:NewGlobalFit:newGF_HoldString "
645        endif
646        Command += funcName+", "                // MakeHoldString() returns "" if there are no holds
647        Command += "MasterCoefs, "
648        Command += "YCumData "
649        if (isAllAtOnce == 1 || isAllAtOnce == 2)               //SRK added || 2
650                Command += "/X=XCumData "
651        endif
652        Command += "/D=FitY "
653        Command += "/E=EpsilonWave "+ResidString
654        //SRK - need to locate constraints, Y/N
655        Variable useConstr=0
656        if (WaveExists(ConstraintWave))
657                useConstr=1
658//              String/G root:Packages:NewGlobalFit:newGF_ConstrWaveStr=GetWavesDataFolder(ConstraintWave, 2)
659//              WAVE constr=root:Packages:NewGlobalFit:newGF_ConstrWaveStr                      //for my hard-wired command
660                Command += "/C="+GetWavesDataFolder(ConstraintWave, 2)
661        endif
662        //eSRK
663        if (doWeighting)
664                Command += "/W=GFWeightWave"
665                if (Options & NewGFOptionWTISSTD)
666                        Command += "/I=1"
667                endif
668        endif
669        SaveDF = GetDataFolder(1)
670DoUpdate
671        SetDataFolder root:Packages:NewGlobalFit
672        Variable/G V_FitQuitReason, V_FitError=0
673        Variable/G V_FitNumIters
674DoUpdate
675        //SRK - MUST hard-wire the FuncFit call to allow the use of a structure fit function, can't use a command to execute!   
676        Variable useCursors = doMasking
677        //cursors are really implemented as a mask wave, that pre-trims the XYS data sets. I need to trim the RES wave inside the
678        // fit function as needed
679        do
680                if(useRes && useEps && useCursors && useConstr)         //do it all
681                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /E=EP /C=ConstraintWave /STRC=sGF
682                        break
683                endif
684               
685                if(useRes && useEps && useCursors)              //no constr
686                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /E=EP /STRC=sGF
687                        break
688                endif
689               
690                if(useRes && useEps && useConstr)               //no crsr
691                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /E=EP /C=ConstraintWave /STRC=sGF
692                        break
693                endif
694               
695                if(useRes && useCursors && useConstr)           //no eps
696                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /C=ConstraintWave /STRC=sGF
697                        break
698                endif
699               
700                if(useRes && useCursors)                //no eps, no constr
701                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /STRC=sGF
702                        break
703                endif
704               
705                if(useRes && useEps)            //no crsr, no constr
706                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /E=EP /STRC=sGF
707                        break
708                endif
709       
710                if(useRes && useConstr)         //no crsr, no eps
711                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /C=ConstraintWave /STRC=sGF
712                        break
713                endif
714               
715                if(useRes)              //just res
716                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /STRC=sGF
717                        break
718                endif
719               
720/////   same as above, but all without useRes
721                if(useEps && useCursors && useConstr)           //do it all
722                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /E=EP /C=ConstraintWave
723                        break
724                endif
725               
726                if(useEps && useCursors)                //no constr
727                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /E=EP
728                        break
729                endif
730               
731                if(useEps && useConstr)         //no crsr
732                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /E=EP /C=ConstraintWave
733                        break
734                endif
735               
736                if(useCursors && useConstr)             //no eps
737                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /C=ConstraintWave
738                        break
739                endif
740               
741                if(useCursors)          //no eps, no constr
742                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY
743                        break
744                endif
745               
746                if(useEps)              //no crsr, no constr
747                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /E=EP
748                        break
749                endif
750       
751                if(useConstr)           //no crsr, no eps
752                        FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY /C=ConstraintWave
753                        break
754                endif
755               
756                //just a plain vanilla fit
757                FuncFit/H=newGF_HoldString /NTHR=0 $funcName MasterCoefs, yw /X=XCumData /W=GFWeightWave /I=1 /D=FitY
758       
759        while(0)
760       
761                //eSRK
762               
763                //SRK not necessary?- compiler can now see FuncFit command...
764//              NVAR/Z fit_V_chisq=V_chisq             
765//              NVAR/Z fit_npnts = V_npnts
766//              NVAR/Z fit_numNaNs = V_numNaNs
767//              NVAR/Z fit_numINFs = V_numINFs
768        SetDataFolder $SaveDF
769       
770        if (V_FitError)
771                if (!quiet)
772                        if (V_FitError & 2)
773                                DoAlert 0, "Global fit stopped due to a singular matrix error."
774                        elseif (V_FitError & 4)
775                                DoAlert 0, "Global fit stopped due to a out of memory error."
776                        elseif (V_FitError & 8)
777                                DoAlert 0, "Global fit stopped because one of your fitting functions returned NaN or INF."
778                        endif
779                endif
780                return V_FitError
781        endif
782       
783        if (!quiet)
784                switch(V_FitQuitReason)
785                        case 0:
786                                print "Global Fit converged normally."
787                                break;
788                        case 1:
789                                print "Global Fit stopped because the limit of iterations was reached."
790                                break;
791                        case 2:
792                                print "Global Fit stopped because the limit of iterations with no decrease in chi-square was reached."
793                                break;
794                        case 3:
795                                print "Hmm... Global Fit stopped for an unknown reason."
796                endswitch
797        endif
798       
799        if (Options & NewGFOptionCOV_MATRIX)
800//              Wave M_Covar
801                Wave M_Covar = root:Packages:NewGlobalFit:M_covar
802                if (Options & NewGFOptionCOR_MATRIX)
803                        Duplicate/O M_Covar, M_Correlation
804                        M_Correlation = M_Covar[p][q]/sqrt(M_Covar[p][p]*M_Covar[q][q])
805                endif
806        endif
807       
808        CoefWave[][0] = MasterCoefs[p]
809        Duplicate/O MasterCoefs, GlobalFitCoefficients
810       
811        Variable histNum=CaptureHistoryStart()          //SRK - for my report
812        if (!quiet)
813                Print "Global fit results"
814                if(V_FitError)
815                                print "\tFit stopped due to an error:"
816                        if (V_FitError & 2)
817                                print "\t\tSingular matrix error"
818                        endif
819                        if (V_FitError & 4)
820                                print "\t\tOut of memory"
821                        endif
822                        if (V_FitError & 8)
823                                print "\t\tFit function returned NaN or Inf"
824                        endif
825                else
826                        switch (V_FitQuitReason)
827                                case 0:
828                                        print "\tFit converged normally"
829                                        break;
830                                case 1:
831                                        print "\tFit exceeded limit of iterations"
832                                        break;
833                                case 2:
834                                        print "\tFit stopped because the user cancelled the fit"
835                                        break;
836                                case 3:
837                                        print "\tFit stopped due to limit of iterations with no decrease in chi-square"
838                                        break;
839                        endswitch
840                endif
841//              print "V_chisq =",V_chisq,"V_npnts=",fit_npnts, "V_numNaNs=", fit_numNaNs, "V_numINFs=",fit_numINFs
842                //SRK
843                print "V_chisq =",V_chisq,"V_npnts=",V_npnts, "V_numNaNs=", V_numNaNs, "V_numINFs=",V_numINFs
844                //eSRK
845                print "Number of iterations:",V_FitNumIters
846                // and print the coefficients by data set into the history
847                Variable numRows = DimSize(privateLinkage, 0)
848                Variable numCols = DimSize(privateLinkage, 1)
849                Variable firstUserow, firstUsecol, linkIndex
850                Wave W_sigma = root:Packages:NewGlobalFit:W_sigma
851                //SRK - adjusting the report format
852//              for (i = 0; i < numRows; i += 1)
853//                      print "Data Set: ",DataSets[i][0]," vs ",DataSets[i][1],"; Function: ",FitFuncNames[privateLinkage[i][FuncPointerCol]]
854//                      for (j = FirstCoefCol; j < (privateLinkage[i][NumFuncCoefsCol] + FirstCoefCol); j += 1)
855//                              linkIndex = privateLinkage[i][j]
856//                             
857//                              FirstUseOfIndexInLinkMatrix(linkIndex, privateLinkage, firstUserow, firstUsecol)
858//                              printf "\t%d\t%s\t%g +- %g", j-FirstCoefCol, CoefNames[privateLinkage[i][j]], MasterCoefs[privateLinkage[i][j]], W_sigma[privateLinkage[i][j]]
859//                              if (CoefWave[privateLinkage[i][j]][%Hold])
860//                                      printf " *HELD* "
861//                              endif
862//                              if ( (firstUserow != i) || (firstUseCol != j) )
863//                                      printf " ** LINKED to data set %s coefficient %d: %s", DataSets[firstUserow][0], firstUseCol-FirstCoefCol, CoefNames[privateLinkage[i][j]]
864//                              endif
865//                              print "\r"
866//                      endfor
867//              endfor
868
869        //ParseFilePath calls account for DataFolders, returning just the end (the intensity wave)
870                for (i = 0; i < numRows; i += 1)
871                        print "Data Set: ",ParseFilePath(0, DataSets[i][0], ":", 1, 0),  "; Function: ",FitFuncNames[privateLinkage[i][FuncPointerCol]]
872                        for (j = FirstCoefCol; j < (privateLinkage[i][NumFuncCoefsCol] + FirstCoefCol); j += 1)
873                                linkIndex = privateLinkage[i][j]
874                               
875                                FirstUseOfIndexInLinkMatrix(linkIndex, privateLinkage, firstUserow, firstUsecol)
876                                printf "\tCoef_%d\t%g +- %g\t", j-FirstCoefCol, MasterCoefs[privateLinkage[i][j]], W_sigma[privateLinkage[i][j]]
877                                if (CoefWave[privateLinkage[i][j]][%Hold])
878                                        printf "*HELD"
879                                endif
880                                if ( (firstUserow != i) || (firstUseCol != j) )
881                                        printf "*LINKED to data set %s; Coef_%d",ParseFilePath(0,  DataSets[firstUserow][0], ":", 1, 0), firstUseCol-FirstCoefCol
882                                endif
883                                print "\r"
884                        endfor
885                endfor
886                String GF_resultStr=CaptureHistory(histNum, 1)
887                //eSRK, simpler reporting of results to the command window
888        endif
889
890// SRK - skip the recalculation, simply extract the results from the FitY destination wave
891// - XCumData is the concatentated x
892// - fitY is the fit result of the same length
893// CoefDataSetLinkage has the first/last index points
894
895
896//      if (FitCurvePoints == 0)
897//              FitCurvePoints = 200
898//      endif
899//
900//      if (options & NewGFOptionAPPEND_RESULTS)
901//              options = options | NewGFOptionMAKE_FIT_WAVES
902//      endif
903//     
904//      if (options & NewGFOptionCALC_RESIDS)
905//              options = options | NewGFOptionMAKE_FIT_WAVES
906//      endif
907//      eSRK
908
909        if ( (options & NewGFOptionMAKE_FIT_WAVES) || (options & NewGFOptionCALC_RESIDS) )
910                Wave/Z fitxW = root:Packages:NewGlobalFit:fitXCumData
911                if (WaveExists(fitxW))
912                        KillWaves fitxW
913                endif
914                Rename xW, fitXCumData          //here, xW is XCumData
915                Wave/Z fitxW = root:Packages:NewGlobalFit:fitXCumData
916                Duplicate/O Yw, fitYCumData     
917                String ListOfFitCurveWaves = ""
918       
919                Variable pt1,pt2
920                for (i = 0; i < DimSize(DataSets, 0); i += 1)
921                        String YFitSet = DataSets[i][0]
922                       
923                        // copy coefficients for each data set into a separate wave
924                        Wave YFit = $YFitSet
925                        saveDF = GetDatafolder(1)
926                        SetDatafolder $GetWavesDatafolder(YFit, 1)
927                        String YWaveName = NameOfWave(YFit)
928                        if (CmpStr(YWaveName[0], "'") == 0)
929                                YWaveName = YWaveName[1, strlen(YWaveName)-2]
930                        endif
931                        // this is a good thing, but doesn't belong here. Individual coefficient waves should be made above
932                        String coefname = CleanupName("Coef_"+YWaveName, 0)
933                        Make/D/O/N=(privateLinkage[i][NumFuncCoefsCol]) $coefname
934                        Wave w = $coefname
935                        w = MasterCoefs[privateLinkage[i][p+FirstCoefCol]]
936//
937                        if (options & NewGFOptionMAKE_FIT_WAVES)
938                        //SRK - extract the fit ywave
939                                pt1 = privateLinkage[i][1]              //first index
940                                pt2 = privateLinkage[i][2]              //last index
941//                              Print "p1,p2 = ",pt1,pt2
942                        //eSRK
943                                String fitCurveName = CleanupName("GFit_"+YWaveName, 0)
944//                              Make/D/O/N=(FitCurvePoints) $fitCurveName
945                                Make/D/O/N=(pt2-pt1+1) $fitCurveName
946                                Wave fitCurveW = $fitCurveName
947                                fitCurveW = FitY[p+pt1]
948                               
949////                            Variable minX, maxX
950////                            WaveStats/Q/R=[privateLinkage[i][FirstPointCol], privateLinkage[i][LastPointCol]] fitxW
951////                            minX = V_min
952////                            maxX = V_max
953////                            if (options & NewGFOptionLOG_DEST_WAVE)
954                                        String XwName=ywavename[0,strlen(ywavename)-2]+"q"
955                                        String fitCurveXName = CleanupName("GFitX_"+YWaveName, 0)
956                                        Make/D/O/N=(pt2-pt1+1) $fitCurveXName
957//                                      Duplicate/O $XwName, $fitCurveXName             //x  matches qvals
958                                        Wave  fitCurveXW = $fitCurveXName
959                                        fitCurveXW = fitxW[p+pt1]
960////                                   
961////                                    Variable logXMin = ln(minX)
962////                                    Variable logXMax = ln(maxX)
963////                                    Variable logXInc = (logXMax - logXMin)/(FitCurvePoints-1)
964////                                   
965////                                    // if there's something wrong with the X range, there will be inf or nan in one of these numbers
966////                                    if ( (numtype(logXMin) != 0) || (numtype(logXMax) != 0) || (numtype(logXInc) != 0) )
967////                                            // something wrong- cancel the log spacing option
968////                                            options = options & ~NewGFOptionLOG_DEST_WAVE
969////                                    else
970////                                            // it's OK- go ahead with log spacing
971////                                            fitCurveXW = exp(logXMin+p*logXInc)
972////                                   
973////                                            // make auxiliary waves required by the fit function
974////                                            // so that we can use the fit function in an assignment
975////                                            Duplicate/O fitCurveXW, root:Packages:NewGlobalFit:XCumData
976////                                            Wave xw = root:Packages:NewGlobalFit:XCumData
977////                                    endif
978////                            endif
979////                            // check this again in case the it was set but cancelled due to bad numbers
980////                            if (!(options & NewGFOptionLOG_DEST_WAVE))
981////                                    SetScale/I x minX, maxX, fitCurveW
982////                           
983////                                    // make auxiliary waves required by the fit function
984////                                    // so that we can use the fit function in an assignment
985////                                    Duplicate/O fitCurveW, root:Packages:NewGlobalFit:XCumData
986////                                    Wave xw = root:Packages:NewGlobalFit:XCumData
987////                                    xw = x
988////                            endif
989//                             
990//                              Duplicate/O fitCurveW, root:Packages:NewGlobalFit:DataSetPointer
991//                              Wave dspw = root:Packages:NewGlobalFit:DataSetPointer
992//                              dspw = i
993//                             
994//                              Duplicate/O privateLinkage, copyOfLinkage
995//                              Make/O/D/N=(1,DimSize(copyOfLinkage, 1)) root:Packages:NewGlobalFit:CoefDataSetLinkage
996//                              Wave tempLinkage = root:Packages:NewGlobalFit:CoefDataSetLinkage
997//                              tempLinkage = copyOfLinkage[i][q]
998//                              tempLinkage[0][FirstPointCol] = 0
999////SRK                         tempLinkage[0][LastPointCol] = FitCurvePoints-1
1000//                              tempLinkage[0][LastPointCol] = numpnts(fitCurveW)-1
1001//                              //SRK toFix
1002//                              // I think this is calculating for only one data set at a time by reducing the dimension of the
1003//                              // CoefDataSetLinkage wave - not good, since the DataSet index is then ALWAYS i=0
1004//                              // and every calculation uses function, resolution, etc of the 0th data set...
1005//                              // (fixed inside NewGlblFitFuncAAOStruct)
1006//                              switch(isAllAtOnce)
1007//                                      case 0:
1008//                                              NewGlblFitFunc(MasterCoefs, fitCurveW, xw)
1009//                                              break
1010//                                      case 1:
1011//                                              NewGlblFitFuncAllAtOnce(MasterCoefs, fitCurveW, xw)
1012//                                              break
1013//                                      case 2:
1014//                                              // call the structure function instead
1015//                                              WAVE sGF.coefW=MasterCoefs
1016//                                              WAVE sGF.yW=fitCurveW
1017//                                              WAVE sGF.xW=fitCurveXW
1018//                                              NewGlblFitFuncAAOStruct(sGF)
1019//                                              break
1020//                                      default:
1021//                                              Abort "switch #2 failed"
1022//                              endswitch
1023////                            if (IsAllAtOnce)
1024////                                    NewGlblFitFuncAllAtOnce(MasterCoefs, fitCurveW, xw)
1025////                            else
1026////                                    NewGlblFitFunc(MasterCoefs, fitCurveW, xw)
1027////                            endif
1028                                       
1029                                //eSRK
1030//                              Duplicate/O copyOfLinkage, root:Packages:NewGlobalFit:CoefDataSetLinkage
1031                               
1032                                if (options & NewGFOptionAPPEND_RESULTS)
1033                                        String graphName = FindGraphWithWave(YFit)
1034                                        if (strlen(graphName) > 0)
1035                                                CheckDisplayed/W=$graphName fitCurveW
1036                                                if (V_flag == 0)
1037                                                        String axisflags = StringByKey("AXISFLAGS", TraceInfo(graphName, YFitSet, 0))
1038//SRK                                           if (options & NewGFOptionLOG_DEST_WAVE)
1039                                                        if (options & NewGFOptionAPPEND_RESULTS)                //dumb way to force true to append y vs x
1040//eSRK
1041                                                                String AppendCmd = "AppendToGraph/W="+graphName+axisFlags+" "+fitCurveName+" vs "+fitCurveXName
1042                                                        else
1043                                                                AppendCmd = "AppendToGraph/W="+graphName+axisFlags+" "+fitCurveName
1044                                                        endif
1045                                                        Execute AppendCmd
1046                                                endif
1047                                        endif
1048                                endif
1049                        endif
1050
1051//BROKEN - residuals are currently not supported
1052//SRK comment them all out                     
1053//                      if (options & NewGFOptionCALC_RESIDS)
1054//                              String resCurveName = CleanupName("GRes_"+YWaveName, 0)
1055//                              Make/D/O/N=(numpnts(YFit)) $resCurveName
1056//                              Wave resCurveW = $resCurveName
1057//                              Wave/Z XFit = $(DataSets[i][1])
1058//                             
1059//                              // make auxiliary waves required by the fit function
1060//                              // so that we can use the fit function in an assignment
1061//                              Duplicate/O resCurveW, root:Packages:NewGlobalFit:XCumData
1062//                              Wave xw = root:Packages:NewGlobalFit:XCumData
1063//                              if (WaveExists(XFit))
1064//                                      xw = XFit
1065//                              else
1066//                                      xw = pnt2x(YFit, p)
1067//                              endif
1068//                             
1069//                              Duplicate/O resCurveW, root:Packages:NewGlobalFit:DataSetPointer
1070//                              Wave dspw = root:Packages:NewGlobalFit:DataSetPointer
1071//                              dspw = i
1072//                             
1073//                              //if (IsAllAtOnce)
1074//                                      Duplicate/O privateLinkage, copyOfLinkage
1075//                                      Make/O/D/N=(1,DimSize(copyOfLinkage, 1)) root:Packages:NewGlobalFit:CoefDataSetLinkage
1076//                                      Wave tempLinkage = root:Packages:NewGlobalFit:CoefDataSetLinkage
1077//                                      tempLinkage = copyOfLinkage[i][q]
1078//                                      tempLinkage[0][FirstPointCol] = 0
1079//                                      tempLinkage[0][LastPointCol] = FitCurvePoints-1
1080//                                      //SRK toFix
1081//                                      switch(isAllAtOnce)
1082//                                              case 0:
1083//                                                      NewGlblFitFunc(MasterCoefs, resCurveW, xw)
1084//                                                      break
1085//                                              case 1:
1086//                                                      NewGlblFitFuncAllAtOnce(MasterCoefs, resCurveW, xw)
1087//                                                      break
1088//                                              case 2:
1089//                                                      // call the structure function instead
1090//                                                      WAVE sGF.coefW=MasterCoefs
1091//                                                      WAVE sGF.yW=resCurveW
1092//                                                      WAVE sGF.xW=xW
1093//                                                      NewGlblFitFuncAAOStruct(sGF)
1094//                                                      break
1095//                                              default:
1096//                                                      Abort "switch #3 failed"
1097//                                      endswitch
1098////                                    if (IsAllAtOnce)
1099////                                            NewGlblFitFuncAllAtOnce(MasterCoefs, resCurveW, xw)
1100////                                    else
1101////                                            NewGlblFitFunc(MasterCoefs, resCurveW, xw)
1102////                                    endif
1103//
1104//                                      //eSRK
1105//                                      resCurveW = YFit[p] - resCurveW[p]
1106//                                      Duplicate/O copyOfLinkage, root:Packages:NewGlobalFit:CoefDataSetLinkage
1107//                              //else
1108//                              //      resCurveW = YFit[p] - NewGlblFitFunc(MasterCoefs, p)
1109//                              //endif
1110//                      endif
1111                       
1112
1113                        SetDataFolder $saveDF   
1114                endfor
1115        endif
1116       
1117        //SRK - generate a simple report
1118        //move the progress window backward, if it's in front
1119        DoWindow/B GlobalFitGraph       
1120        String topGraph= WinName(0,1)
1121        Generate_GF_Report(topGraph,GF_resultStr)
1122       
1123        //eSRK
1124       
1125        return 0
1126end
1127
1128static constant GF_FuncType_Regular = 0
1129static constant GF_FuncType_AllAtOnce = 1
1130static constant GF_FuncType_BadFunc = -1
1131static constant GF_FuncType_NoFunc = -2
1132//SRK
1133static constant GF_FuncType_AAOStruct = 2
1134//eSRK
1135
1136//SRK - modified logic to detect my struct functions (which are also AAO)
1137// and return a new value
1138static Function GF_FunctionType(functionName)
1139        String functionName
1140       
1141        Variable FuncType = GF_FuncType_BadFunc
1142               
1143        string FitFuncs = FunctionList("*", ";", "VALTYPE:1,NPARAMS:2")
1144//      print FitFuncs
1145        if (FindListItem(functionName, FitFuncs) >= 0)
1146                FuncType = GF_FuncType_Regular
1147        else
1148                FitFuncs = FunctionList("*", ";", "VALTYPE:1,NPARAMS:3")
1149                if (FindListItem(functionName, FitFuncs) >= 0)
1150                        FuncType = GF_FuncType_AllAtOnce
1151                endif
1152        endif
1153       
1154        //SRK - still not found, try one param, this would be struct
1155        if (FuncType == GF_FuncType_BadFunc)
1156                FitFuncs = FunctionList("*", ";", "VALTYPE:1,NPARAMS:1")
1157                if (FindListItem(functionName, FitFuncs) >= 0)
1158                        FuncType = GF_FuncType_AAOStruct
1159                endif
1160        endif
1161        //eSRK
1162       
1163        if (FuncType == GF_FuncType_BadFunc)
1164                Variable funcExists = Exists(functionName)
1165                if ((funcExists != 6) && (funcExists != 3) )
1166                        FuncType = GF_FuncType_NoFunc
1167                endif
1168        endif
1169        return FuncType
1170end
1171
1172static Function FirstUseOfIndexInLinkMatrix(index, linkMatrix, row, col)
1173        Variable index
1174        Wave linkMatrix
1175        Variable &row
1176        Variable &col
1177       
1178        Variable i, j
1179        Variable numRows = DimSize(linkMatrix, 0)
1180        Variable numCols = DimSize(linkMatrix, 1)
1181        for (i = 0; i < numRows; i += 1)
1182                for (j = FirstCoefCol; j < numCols; j += 1)
1183                        if (linkMatrix[i][j] == index)
1184                                row = i
1185                                col = j
1186                                return 0
1187                        endif
1188                endfor
1189        endfor
1190       
1191        row = -1
1192        col = -1
1193        return -1
1194end
1195
1196// Checks list of data sets for consistency, etc.
1197// Makes the cumulative data set waves.
1198static Function NewGF_CheckDSets_BuildCumWaves(DataSets, linkageMatrix, doWeighting, doMasking, errorWaveName, errorWaveRow, errorWaveColumn)
1199        Wave/T DataSets
1200        Wave linkageMatrix
1201        Variable &doWeighting
1202        Variable &doMasking
1203        String &errorWaveName
1204        Variable &errorWaveRow
1205        Variable &errorWaveColumn
1206       
1207        errorWaveName = ""
1208
1209        Variable i, j
1210        String XSet, YSet
1211        Variable numSets = DimSize(DataSets, 0)
1212        Variable wavePoints
1213        Variable npnts
1214       
1215        if (numSets == 0)
1216                return 0
1217        endif
1218       
1219        Variable totalPoints = 0
1220       
1221        Variable MaskCol = FindDimLabel(DataSets, 1, "Masks")
1222        doMasking = 0
1223        if (MaskCol >= 0)
1224//              Make/D/N=(totalPoints)/O root:Packages:NewGlobalFit:GFMaskWave
1225                doMasking = 1
1226        endif
1227
1228        doWeighting = 0
1229        Variable WeightCol = FindDimLabel(DataSets, 1, "Weights")
1230        if (WeightCol >= 0)
1231//              Make/D/N=(totalPoints)/O root:Packages:NewGlobalFit:GFWeightWave
1232                doWeighting = 1
1233        endif
1234       
1235        // pre-scan to find the total number of points. This is done so that the concatenated wave
1236        // can be made at the final size all at one time, avoiding problems with virtual memory
1237        // that can be caused by re-sizing a memory block many times.
1238       
1239        // JW 040818 Failing to check for NaN's in the data waves causes a failure of synchronization between
1240        // the data structures and the data passed to the fit function by FuncFit. I will have to check for NaN's
1241        // and not include them.
1242        // I am removing the check for masked points in this loop. If there are masked points or NaN's, the wave
1243        // will be too big and will be reduced at the end. However, I will do a check here for bad wave names or bad numbers of
1244        // points so that I don't have to clutter up the second loop with checks.
1245        for (i = 0; i < numSets; i += 1)
1246                // check the Y wave
1247                YSet = DataSets[i][0]
1248                XSet = DataSets[i][1]
1249                Wave/Z Ysetw = $YSet
1250                Wave/Z Xsetw = $XSet
1251                if (!WaveExists(YSetw))
1252                        errorWaveName = YSet
1253                        errorWaveRow = i
1254                        errorWaveColumn = 0
1255                        return NewGlobalFitBAD_YWAVE
1256                endif
1257                wavePoints = numpnts(Ysetw)
1258               
1259                // check the X wave
1260                if (cmpstr(XSet, "_Calculated_") != 0)
1261                        if (!WaveExists(Xsetw))
1262                                errorWaveName = XSet
1263                                errorWaveRow = i
1264                                errorWaveColumn = 1
1265                                return NewGlobalFitBAD_XWAVE
1266                        endif
1267                        if (wavePoints != numpnts(Xsetw))
1268                                errorWaveRow = i
1269                                errorWaveColumn = 1
1270                                return NewGlobalFitXWaveBADPOINTS
1271                        endif
1272                endif           
1273               
1274                // check mask wave if necessary
1275                if (doMasking)
1276                        Wave/Z mw = $(DataSets[i][MaskCol])
1277                        if (!WaveExists(mw))
1278                                errorWaveRow = i
1279                                errorWaveColumn = MaskCol
1280                                return NewGlobalFitNOMSKWAVE
1281                        endif
1282                        if (wavePoints != numpnts(mw))
1283                                errorWaveRow = i
1284                                errorWaveColumn = MaskCol
1285                                return NewGlobalFitMSKWAVEBADPOINTS
1286                        endif
1287                endif
1288               
1289                // check weighting wave if necessary
1290                if (doWeighting)
1291                        Wave/Z ww = $(DataSets[i][WeightCol])
1292                        if (!WaveExists(ww))
1293                                errorWaveRow = i
1294                                errorWaveColumn = WeightCol
1295                                return NewGlobalFitNOWTWAVE
1296                        endif
1297                        if (wavePoints != numpnts(ww))
1298                                errorWaveRow = i
1299                                errorWaveColumn = WeightCol
1300                                return NewGlobalFitWTWAVEBADPOINTS
1301                        endif
1302                endif
1303
1304                totalPoints += numpnts(Ysetw)
1305        endfor
1306       
1307        if (doWeighting)
1308                Make/D/N=(totalPoints)/O root:Packages:NewGlobalFit:GFWeightWave
1309        endif
1310
1311        // make the waves that will contain the concatenated data sets and the wave that points
1312        // to the appropriate row in the data set linkage matrix
1313        Make/D/N=(totalPoints)/O root:Packages:NewGlobalFit:XCumData, root:Packages:NewGlobalFit:YCumData
1314        Make/U/W/N=(totalPoints)/O root:Packages:NewGlobalFit:DataSetPointer
1315       
1316        Wave Xw = root:Packages:NewGlobalFit:XCumData
1317        Wave Yw = root:Packages:NewGlobalFit:YCumData
1318        Wave DataSetPointer = root:Packages:NewGlobalFit:DataSetPointer
1319        Wave/Z Weightw = root:Packages:NewGlobalFit:GFWeightWave
1320//      Wave/Z Maskw = root:Packages:NewGlobalFit:GFMaskWave
1321       
1322        Variable realTotalPoints = 0
1323        Variable wavePoint = 0
1324
1325        // second pass through the list, this time copying the data into the concatenated sets, and
1326        // setting index numbers in the index wave
1327        for (i = 0; i < numSets; i += 1)
1328                YSet = DataSets[i][0]
1329                XSet = DataSets[i][1]
1330                Wave/Z Ysetw = $YSet
1331                Wave/Z Xsetw = $XSet
1332                Wave/Z mw = $(DataSets[i][MaskCol])
1333                Wave/Z ww = $(DataSets[i][WeightCol])
1334
1335                wavePoints = numpnts(Ysetw)
1336                for (j = 0; j < wavePoints; j += 1)
1337                        if (numtype(Ysetw[j]) != 0)
1338                                continue
1339                        endif
1340                       
1341                        if (doMasking)
1342                                if ( (numtype(mw[j]) != 0) || (mw[j] == 0) )
1343                                        continue
1344                                endif
1345                        endif
1346                       
1347                        if (doWeighting)
1348                                if ( (numtype(ww[j]) != 0) || (ww[j] == 0) )
1349                                        continue
1350                                endif
1351                        endif
1352                       
1353                        DataSetPointer[wavePoint] = i
1354                       
1355                        Yw[wavePoint] = Ysetw[j]
1356
1357                        if (cmpstr(XSet, "_Calculated_") == 0)
1358                                Xw[wavePoint] = pnt2x(Ysetw, j)
1359                        else
1360                                if (numtype(Xsetw[j]) != 0)
1361                                        continue
1362                                endif
1363                                Xw[wavePoint] = Xsetw[j]
1364                        endif
1365                       
1366                        if (doWeighting)
1367                                Weightw[wavePoint] = ww[j]
1368                        endif
1369                       
1370                        wavePoint += 1
1371                endfor
1372               
1373                linkageMatrix[i][FirstPointCol] = realTotalPoints
1374                linkageMatrix[i][LastPointCol] = wavePoint-1
1375                realTotalPoints = wavePoint
1376        endfor
1377       
1378        if (totalPoints > realTotalPoints)
1379                Redimension/N=(realTotalPoints) Yw, Xw
1380                if (doWeighting)
1381                        Redimension/N=(realTotalPoints) Weightw
1382                endif                   
1383        endif
1384       
1385        return numSets
1386end
1387
1388//********************
1389//      The GUI part
1390//********************
1391
1392static Function InitNewGlobalFitGlobals()
1393       
1394        String saveFolder = GetDataFolder(1)
1395       
1396        NewDataFolder/O/S root:Packages
1397        NewDataFolder/O/S NewGlobalFit
1398       
1399        Make/O/T/N=(1,4,2) NewGF_DataSetListWave = ""
1400        SetDimLabel 1, 0, 'Y Waves', NewGF_DataSetListWave
1401        SetDimLabel 1, 1, 'X Waves', NewGF_DataSetListWave
1402        SetDimLabel 1, 2, Function, NewGF_DataSetListWave
1403        SetDimLabel 1, 3, '# Coefs', NewGF_DataSetListWave
1404       
1405        Make/O/T/N=(1,1,2) NewGF_MainCoefListWave = ""
1406        SetDimLabel 1, 0, 'Coefs- K0', NewGF_MainCoefListWave
1407
1408        Make/O/N=(1,4,2) NewGF_DataSetListSelWave = 0   
1409
1410        Make/O/N=(1,1,2) NewGF_MainCoefListSelWave = 0
1411        SetDimLabel 2, 1, backColors, NewGF_MainCoefListSelWave
1412        ColorTab2Wave Pastels
1413        Wave M_colors
1414        Duplicate/O M_colors, NewGF_LinkColors
1415        Variable i, index = 0, size = DimSize(M_colors, 0)
1416        for (i = 0; i < size; i += 1)
1417                NewGF_LinkColors[i][] = M_colors[index][q]
1418                index += 149
1419                if (index >= size)
1420                        index -= size
1421                endif
1422        endfor
1423        KillWaves/Z M_colors
1424       
1425        Make/O/T/N=(1,5) NewGF_CoefControlListWave = ""
1426        Make/O/N=(1,5) NewGF_CoefControlListSelWave
1427        SetDimLabel 1, 0, 'Data Set', NewGF_CoefControlListWave
1428        SetDimLabel 1, 1, Name, NewGF_CoefControlListWave
1429        SetDimLabel 1, 2, 'Initial Guess', NewGF_CoefControlListWave
1430        SetDimLabel 1, 3, 'Hold?', NewGF_CoefControlListWave
1431        SetDimLabel 1, 4, Epsilon, NewGF_CoefControlListWave
1432        NewGF_CoefControlListSelWave[][3] = 0x20
1433       
1434        Variable/G NewGF_RebuildCoefListNow = 1
1435       
1436        Variable points = NumVarOrDefault("FitCurvePoints", 200)
1437        Variable/G FitCurvePoints = points
1438       
1439        String setupName = StrVarOrDefault("NewGF_NewSetupName", "NewGlobalFitSetup")
1440        String/G NewGF_NewSetupName = setupName
1441
1442        SetDataFolder $saveFolder
1443end
1444
1445static Function InitNewGlobalFitPanel()
1446
1447        if (wintype("NewGlobalFitPanel") == 0)
1448                InitNewGlobalFitGlobals()
1449                fNewGlobalFitPanel()
1450        else
1451                DoWindow/F NewGlobalFitPanel
1452        endif
1453end
1454
1455static Function UnloadNewGlobalFit()
1456        if (WinType("NewGlobalFitPanel") == 7)
1457                DoWindow/K NewGlobalFitPanel
1458        endif
1459        if (WinType("GlobalFitGraph") != 0)
1460                DoWindow/K GlobalFitGraph
1461        endif
1462        if (WinType("NewGF_GlobalFitConstraintPanel"))
1463                DoWindow/K NewGF_GlobalFitConstraintPanel
1464        endif
1465        if (WinType("NewGF_WeightingPanel"))
1466                DoWindow/K NewGF_WeightingPanel
1467        endif
1468        if (WinType("NewGF_GlobalFitMaskingPanel"))
1469                DoWindow/K NewGF_GlobalFitMaskingPanel
1470        endif
1471        Execute/P "DELETEINCLUDE  <Global Fit 2>"
1472        Execute/P "COMPILEPROCEDURES "
1473        KillDataFolder root:Packages:NewGlobalFit
1474end
1475
1476static constant NewGF_DSList_YWaveCol = 0
1477static constant NewGF_DSList_XWaveCol = 1
1478static constant NewGF_DSList_FuncCol = 2
1479static constant NewGF_DSList_NCoefCol = 3
1480
1481// moved to separate wave
1482//static constant NewGF_DSList_FirstCoefCol = 4
1483static constant NewGF_DSList_FirstCoefCol = 0
1484
1485static Function fNewGlobalFitPanel()
1486
1487        Variable defLeft = 50
1488        Variable defTop = 70
1489        Variable defRight = 719
1490        Variable defBottom = 447
1491       
1492        String fmt="NewPanel/K=1/W=(%s) as \"Global Analysis\""
1493        String cmd = WC_WindowCoordinatesSprintf("NewGlobalFitPanel", fmt, defLeft, defTop, defRight, defBottom, 0)
1494        Execute cmd
1495
1496//      NewPanel/K=1/W=(156,70,829,443) as "Global Analysis"
1497        DoWindow/C NewGlobalFitPanel
1498
1499        DefineGuide Tab0AreaLeft={FL,13}                        // this is changed to FR, 25 when tab 0 is hidden
1500        DefineGuide Tab0AreaRight={FR,-10}
1501        DefineGuide TabAreaTop={FT,28}
1502        DefineGuide TabAreaBottom={FB,-118}
1503        DefineGuide Tab1AreaLeft={FR,25}                        // this is changed to FL and appropriate offset when tab 1 is shown
1504        DefineGuide Tab1AreaRight={FR,800}
1505        DefineGuide GlobalControlAreaTop={FB,-109}
1506       
1507        TabControl NewGF_TabControl,pos={10,7},size={654,255},proc=WM_NewGlobalFit1#NewGF_TabControlProc
1508        TabControl NewGF_TabControl,tabLabel(0)="Data Sets and Functions"
1509        TabControl NewGF_TabControl,tabLabel(1)="Coefficient Control",value= 0
1510       
1511        NewPanel/FG=(Tab0AreaLeft, TabAreaTop, Tab0AreaRight, TabAreaBottom) /HOST=#
1512                RenameWindow #,Tab0ContentPanel
1513                ModifyPanel frameStyle=0, frameInset=0
1514       
1515//              ListBox NewGF_DataSetsList,pos={3,133},size={443,196}, listWave=root:Packages:NewGlobalFit:NewGF_DataSetListWave
1516//              ListBox NewGF_DataSetsList,selWave=root:Packages:NewGlobalFit:NewGF_DataSetListSelWave,proc=WM_NewGlobalFit1#NewGF_DataSetListBoxProc
1517//              ListBox NewGF_DataSetsList,widths={100,100,100,50,90}, mode=10,editStyle=1,frame=4, colorWave = root:Packages:NewGlobalFit:NewGF_LinkColors
1518               
1519                GroupBox NewGF_DataSetsGroup,pos={2,3},size={640,36}
1520       
1521                        TitleBox NewGF_DataSetsGroupTitle,pos={23,14},size={57,12},title="Data Sets:",fSize=10,frame=0
1522                        TitleBox NewGF_DataSetsGroupTitle,fStyle=1
1523
1524                        PopupMenu NewGF_AddDataSetMenu,pos={88,11},size={120,20},proc=WM_NewGlobalFit1#NewGF_AddYWaveMenuProc,title="Add Data Sets"
1525                        PopupMenu NewGF_AddDataSetMenu,mode=0,bodyWidth= 120,value= #"NewGF_YWaveList(1)"
1526
1527                        PopupMenu NewGF_SetDataSetMenu,pos={370,11},size={120,20},proc=WM_NewGlobalFit1#NewGF_SetDataSetMenuProc,title="Set Y Wave"
1528                        PopupMenu NewGF_SetDataSetMenu,mode=0,bodyWidth= 120,value= #"NewGF_YWaveList(0)"
1529
1530                        PopupMenu NewGF_SetXDataSetMenu,pos={229,11},size={120,20},proc=WM_NewGlobalFit1#NewGF_SetXWaveMenuProc,title="Set X Wave"
1531                        PopupMenu NewGF_SetXDataSetMenu,mode=0,bodyWidth= 120,value= #"NewGF_XWaveList()"
1532
1533                        PopupMenu NewGF_RemoveDataSetMenu1,pos={512,11},size={120,20},proc=WM_NewGlobalFit1#NewGF_RemoveDataSetsProc,title="Remove"
1534                        PopupMenu NewGF_RemoveDataSetMenu1,mode=0,bodyWidth= 120,value= #"NewGF_RemoveMenuList()"
1535
1536                PopupMenu NewGF_SetFunctionMenu,pos={7,51},size={120,20},proc=NewGF_SetFuncMenuProc,title="Choose Fit Func"
1537                PopupMenu NewGF_SetFunctionMenu,mode=0,bodyWidth= 120,value= #"NewGF_FitFuncList()"
1538
1539                GroupBox NewGF_CoefficientsGroup,pos={134,43},size={508,36}
1540
1541                        TitleBox NewGF_Tab0CoefficientsTitle,pos={145,54},size={73,12},title="Coefficients:"
1542                        TitleBox NewGF_Tab0CoefficientsTitle,fSize=10,frame=0,fStyle=1
1543
1544                        Button NewGF_LinkCoefsButton,pos={224,51},size={70,20},proc=NewGF_LinkCoefsButtonProc,title="Link"
1545
1546                        Button NewGF_UnLinkCoefsButton,pos={301,51},size={70,20},proc=NewGF_UnLinkCoefsButtonProc,title="Unlink"
1547
1548                        PopupMenu NewGF_SelectAllCoefMenu,pos={378,51},size={124,20},proc=WM_NewGlobalFit1#NewGF_SelectAllCoefMenuProc,title="Select"
1549                        PopupMenu NewGF_SelectAllCoefMenu,mode=0,bodyWidth= 124,value= #"WM_NewGlobalFit1#NewGF_ListFunctionsAndCoefs()"
1550
1551                        PopupMenu NewGF_SelectAlsoCoefMenu,pos={509,51},size={124,20},proc=WM_NewGlobalFit1#NewGF_SelectAllCoefMenuProc,title="Add To Selection"
1552                        PopupMenu NewGF_SelectAlsoCoefMenu,mode=0,bodyWidth= 124,value= #"WM_NewGlobalFit1#NewGF_ListFunctionsAndCoefs()"
1553
1554                GroupBox NewGF_Tab0ListGroup,pos={2,86},size={641,143}
1555
1556                        ListBox NewGF_DataSetsList,pos={4,88},size={300,139},proc=WM_NewGlobalFit1#NewGF_DataSetListBoxProc
1557                        ListBox NewGF_DataSetsList,listWave=root:Packages:NewGlobalFit:NewGF_DataSetListWave
1558                        ListBox NewGF_DataSetsList,selWave=root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
1559                        ListBox NewGF_DataSetsList,mode= 10,editStyle= 1,widths= {81,81,81,42},frame=1,userColumnResize=1
1560       
1561                        ListBox NewGF_Tab0CoefList,pos={305,88},size={336,139},proc=WM_NewGlobalFit1#NewGF_DataSetListBoxProc
1562                        ListBox NewGF_Tab0CoefList,listWave=root:Packages:NewGlobalFit:NewGF_MainCoefListWave
1563                        ListBox NewGF_Tab0CoefList,selWave=root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
1564                        ListBox NewGF_Tab0CoefList,colorWave=root:Packages:NewGlobalFit:NewGF_LinkColors
1565                        ListBox NewGF_Tab0CoefList,mode= 10,editStyle= 1,widths= {100},frame=1,userColumnResize=1
1566
1567        SetActiveSubwindow ##
1568       
1569        NewPanel/W=(119,117,359,351)/FG=(Tab1AreaLeft,TabAreaTop,Tab1AreaRight,TabAreaBottom)/HOST=#
1570                RenameWindow #, Tab1ContentPanel
1571                ModifyPanel frameStyle=0, frameInset=0
1572               
1573                ListBox NewGF_CoefControlList,pos={4,34},size={440,291},proc = WM_NewGlobalFit1#NewGF_CoefListBoxProc,frame=4
1574                ListBox NewGF_CoefControlList,listWave=root:Packages:NewGlobalFit:NewGF_CoefControlListWave
1575                ListBox NewGF_CoefControlList,selWave=root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
1576                ListBox NewGF_CoefControlList,mode= 10,editStyle= 1,widths= {15,15,7,4,5},userColumnResize=1
1577               
1578                TitleBox NewGF_CoefControlIGTitle,pos={135,9},size={75,15},title="Initial guess:"
1579                TitleBox NewGF_CoefControlIGTitle,fSize=12,frame=0,anchor= RC
1580
1581                PopupMenu NewGF_SetCoefsFromWaveMenu,pos={219,7},size={100,20},title="Set from Wave",mode=0,value=NewGF_ListInitGuessWaves(0, 0)
1582                PopupMenu NewGF_SetCoefsFromWaveMenu,proc=NewGF_SetCoefsFromWaveProc
1583
1584                PopupMenu NewGF_SaveCoefstoWaveMenu,pos={343,7},size={100,20},title="Save to Wave",mode=0,value="New Wave...;-;"+NewGF_ListInitGuessWaves(0, 0)
1585                PopupMenu NewGF_SaveCoefstoWaveMenu,proc=NewGF_SaveCoefsToWaveProc
1586
1587        SetActiveSubwindow ##
1588       
1589        DefineGuide GlobalControlAreaLeft={FR,-200}
1590
1591        NewPanel/W=(495,313,643,351)/FG=(FL,GlobalControlAreaTop,FR,FB)/HOST=#
1592                ModifyPanel frameStyle=0, frameInset=0
1593                RenameWindow #,NewGF_GlobalControlArea
1594       
1595                GroupBox NewGF_GlobalGroup,pos={5,3},size={478,101}
1596
1597                        CheckBox NewGF_ConstraintsCheckBox,pos={330,49},size={79,14},proc=WM_NewGlobalFit1#ConstraintsCheckProc,title="Constraints..."
1598                        CheckBox NewGF_ConstraintsCheckBox,value= 0
1599       
1600                        CheckBox NewGF_WeightingCheckBox,pos={330,11},size={70,14},proc=WM_NewGlobalFit1#NewGF_WeightingCheckProc,title="Weighting..."
1601                        CheckBox NewGF_WeightingCheckBox,value= 0
1602       
1603                        CheckBox NewGF_MaskingCheckBox,pos={330,30},size={63,14},proc=WM_NewGlobalFit1#NewGF_MaskingCheckProc,title="Masking..."
1604                        CheckBox NewGF_MaskingCheckBox,value= 0
1605       
1606                        CheckBox NewGF_DoCovarMatrix,pos={190,49},size={102,14},proc=WM_NewGlobalFit1#NewGF_CovMatrixCheckProc,title="Covariance Matrix"
1607                        CheckBox NewGF_DoCovarMatrix,value= 0,disable=2//SRK
1608       
1609                        CheckBox NewGF_CorrelationMatrixCheckBox,pos={212,69},size={103,14},proc=WM_NewGlobalFit1#NewGF_CorMatrixCheckProc,title="Correlation Matrix"
1610                        CheckBox NewGF_CorrelationMatrixCheckBox,value= 0,disable=2//SRK
1611       
1612                        CheckBox NewGF_MakeFitCurvesCheck,pos={12,11},size={118,14},proc=WM_NewGlobalFit1#NewGF_FitCurvesCheckProc,title="Make Fit Curve Waves"
1613                        CheckBox NewGF_MakeFitCurvesCheck,value= 1
1614       
1615                        CheckBox NewGF_AppendResultsCheckbox,pos={34,30},size={143,14},proc=WM_NewGlobalFit1#NewGF_AppendResultsCheckProc,title="And Append Them to Graphs"
1616                        CheckBox NewGF_AppendResultsCheckbox,value=0,disable=2//SRK
1617       
1618                        CheckBox NewGF_DoResidualCheck,pos={34,69},size={104,14},proc=WM_NewGlobalFit1#NewGF_CalcResidualsCheckProc,title="Calculate Residuals"
1619                        CheckBox NewGF_DoResidualCheck,value= 0,disable=2//SRK
1620       
1621                        CheckBox NewGF_DoDestLogSpacingCheck,pos={34,86},size={108,14},title="Logarithmic Spacing"
1622                        CheckBox NewGF_DoDestLogSpacingCheck,value=0,disable=2//SRK
1623
1624                        SetVariable NewGF_SetFitCurveLength,pos={37,49},size={131,15},title="Fit Curve Points:"
1625                        SetVariable NewGF_SetFitCurveLength,limits={2,inf,1},value= root:Packages:NewGlobalFit:FitCurvePoints,bodyWidth= 50,disable=2//SRK
1626       
1627                        CheckBox NewGF_Quiet,pos={190,30},size={98,14},title="No History Output"
1628                        CheckBox NewGF_Quiet,value=0,disable=2//SRK
1629       
1630                        CheckBox NewGF_FitProgressGraphCheckBox,pos={190,11},size={103,14},title="Fit Progress Graph"
1631                        CheckBox NewGF_FitProgressGraphCheckBox,value= 1
1632       
1633                        Button DoFitButton,pos={421,10},size={50,20},proc=WM_NewGlobalFit1#NewGF_DoTheFitButtonProc,title="Fit!"
1634
1635                GroupBox NewGF_SaveSetupGroup,pos={487,3},size={178,101},title="Setup"
1636
1637                        SetVariable NewGF_SaveSetSetName,pos={496,20},size={162,15},title="Name:"
1638                        SetVariable NewGF_SaveSetSetName,value= root:Packages:NewGlobalFit:NewGF_NewSetupName,bodyWidth= 130
1639       
1640                        CheckBox NewGF_StoredSetupOverwriteOKChk,pos={508,39},size={80,14},title="Overwrite OK"
1641                        CheckBox NewGF_StoredSetupOverwriteOKChk,value= 0
1642       
1643                        Button NewGF_SaveSetupButton,pos={605,36},size={50,20},proc=WM_NewGlobalFit1#NewGF_SaveSetupButtonProc,title="Save"
1644       
1645                        PopupMenu NewGF_RestoreSetupMenu,pos={522,78},size={107,20},proc=WM_NewGlobalFit1#NewGF_RestoreSetupMenuProc,title="Restore Setup"
1646                        PopupMenu NewGF_RestoreSetupMenu,mode=0,value= #"WM_NewGlobalFit1#NewGF_ListStoredSetups()"
1647
1648        SetActiveSubwindow ##
1649       
1650        SetWindow NewGlobalFitPanel, hook = WC_WindowCoordinatesHook
1651        SetWindow NewGlobalFitPanel, hook(NewGF_Resize) = NewGF_PanelResizeHook
1652
1653        NewGF_MoveControls()
1654end
1655
1656Function IsMinimized(windowName)
1657        String windowName
1658       
1659        if (strsearch(WinRecreation(windowName, 0), "MoveWindow 0, 0, 0, 0", 0, 2) > 0)
1660                return 1
1661        endif
1662       
1663        return 0
1664end
1665
1666Function NewGF_PanelResizeHook(H_Struct)
1667        STRUCT WMWinHookStruct &H_Struct
1668       
1669        Variable statusCode = 0
1670
1671if (H_Struct.eventCode == 4)
1672        return 0
1673endif
1674//print "event code: ", H_Struct.eventCode, "; Window: ", H_Struct.winName
1675       
1676        switch (H_Struct.eventCode)
1677                case 2:                 // kill
1678                        if (WinType("NewGF_GlobalFitConstraintPanel"))
1679                                DoWindow/K NewGF_GlobalFitConstraintPanel
1680                        endif
1681                        if (WinType("NewGF_WeightingPanel"))
1682                                DoWindow/K NewGF_WeightingPanel
1683                        endif
1684                        if (WinType("NewGF_GlobalFitMaskingPanel"))
1685                                DoWindow/K NewGF_GlobalFitMaskingPanel
1686                        endif
1687                        break
1688                case 6:                 // resize
1689                        if (IsMinimized(H_Struct.winName))
1690                                break;
1691                        endif
1692                        NewGF_MainPanelMinWindowSize()
1693                        NewGF_MoveControls()
1694                        break
1695        endswitch
1696       
1697        return statusCode               // 0 if nothing done, else 1
1698End
1699
1700static constant NewGF_MainPanelMinWidth = 669
1701static constant NewGF_MainPanelMinHeight = 377
1702
1703static constant NewGF_TabWidthMargin = 15
1704static constant NewGF_TabHeightMargin = 122
1705
1706static constant NewGF_Tab0ListGroupWidthMargin  = 5
1707static constant NewGF_Tab0ListGroupHeightMargin = 88
1708
1709static constant NewGF_DataSetListGrpWidthMargin = 341
1710static constant NewGF_DataSetListGrpHghtMargin = 4
1711
1712static constant NewGF_Tab0CoefListTopMargin = 88
1713static constant NewGF_Tab0CoefListLeftMargin = 1
1714static constant NewGF_Tab0CoefListRightMargin = 2
1715
1716static constant NewGF_CoefListWidthMargin = 10
1717static constant NewGF_CoefListHeightMargin = 40
1718
1719// all dimensions are in points
1720static Function NewGF_MainPanelMinWindowSize()
1721
1722        GetWindow NewGlobalFitPanel, wsize
1723        Variable minimized= (V_right == V_left) && (V_bottom==V_top)
1724        if( minimized )
1725                return 0
1726        endif
1727        Variable width= (V_right - V_left)
1728        Variable height= (V_bottom - V_top)
1729        width= max(width, NewGF_MainPanelMinWidth*72/ScreenResolution)
1730        height= max(height, NewGF_MainPanelMinHeight*72/ScreenResolution)
1731        MoveWindow/W=NewGlobalFitPanel V_left, V_top, V_left+width, V_top+height
1732End
1733
1734static Function NewGF_MoveControls()
1735
1736        GetWindow NewGlobalFitPanel wsizeDC
1737        Variable Width = (V_right - V_left)
1738        Variable Height = (V_bottom - V_top)
1739        TabControl NewGF_TabControl, win=NewGlobalFitPanel,size={width-NewGF_TabWidthMargin, height-NewGF_TabHeightMargin}
1740
1741        ControlInfo/W=NewGlobalFitPanel NewGF_TabControl
1742        switch(V_value)
1743                case 0:
1744                        GetWindow NewGlobalFitPanel#Tab0ContentPanel wsizeDC
1745                        Width = (V_right - V_left) - NewGF_Tab0ListGroupWidthMargin
1746                        Height = (V_bottom - V_top) - NewGF_Tab0ListGroupHeightMargin
1747                        GroupBox NewGF_Tab0ListGroup, win=NewGlobalFitPanel#Tab0ContentPanel, size={width, height}
1748                        ControlInfo/W=NewGlobalFitPanel#Tab0ContentPanel NewGF_DataSetsList
1749                        Variable listwidth = V_width            // constant width
1750                        height -= NewGF_DataSetListGrpHghtMargin
1751                        ListBox NewGF_DataSetsList, win=NewGlobalFitPanel#Tab0ContentPanel, size={listwidth, height}
1752                        ControlInfo/W=NewGlobalFitPanel#Tab0ContentPanel NewGF_DataSetsList
1753                        Variable top = V_top
1754                        Variable left = V_Left + V_width + 1
1755                        ControlInfo/W=NewGlobalFitPanel#Tab0ContentPanel NewGF_Tab0ListGroup
1756                        listwidth = V_left + V_width - 2 - left
1757                        ListBox NewGF_Tab0CoefList, win=NewGlobalFitPanel#Tab0ContentPanel, pos={left, top}, size={listwidth, height}
1758                        break;
1759                case 1:
1760                        GetWindow NewGlobalFitPanel#Tab1ContentPanel wsizeDC
1761                        Width = (V_right - V_left)
1762                        Height = (V_bottom - V_top)
1763                        ListBox NewGF_CoefControlList, win=NewGlobalFitPanel#Tab1ContentPanel,size={width-NewGF_CoefListWidthMargin, height-NewGF_CoefListHeightMargin}
1764                        break;
1765        endswitch
1766end
1767
1768static Function/S NewGF_ListStoredSetups()
1769
1770        String SaveDF = GetDataFolder(1)
1771        SetDataFolder root:Packages:
1772       
1773        if (!DataFolderExists("NewGlobalFit_StoredSetups"))
1774                SetDataFolder $saveDF
1775                return "\\M1(No Stored Setups"
1776        endif
1777       
1778        SetDataFolder NewGlobalFit_StoredSetups
1779       
1780        Variable numDFs = CountObjects(":", 4)
1781        if (numDFs == 0)
1782                SetDataFolder $saveDF
1783                return "\\M1(No Stored Setups"
1784        endif
1785       
1786        Variable i
1787        String theList = ""
1788        for (i = 0; i < numDFs; i += 1)
1789                theList += (GetIndexedObjName(":", 4, i)+";")
1790        endfor
1791       
1792        SetDataFolder $saveDF
1793        return theList
1794end
1795
1796
1797static Function NewGF_SaveSetupButtonProc(ctrlName) : ButtonControl
1798        String ctrlName
1799
1800        SVAR NewGF_NewSetupName = root:Packages:NewGlobalFit:NewGF_NewSetupName
1801        String SaveDF = GetDataFolder(1)
1802        SetDataFolder root:Packages:
1803        NewDataFolder/O/S NewGlobalFit_StoredSetups
1804
1805        if (CheckName(NewGF_NewSetupName, 11))
1806                if (DataFolderExists(NewGF_NewSetupName))
1807                        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_StoredSetupOverwriteOKChk
1808                        if (V_value)
1809                                KillDataFolder $NewGF_NewSetupName
1810                        else
1811                                DoAlert 1, "The setup name "+NewGF_NewSetupName+" already exists. Make a unique name and continue?"
1812                                if (V_flag == 1)
1813                                        NewGF_NewSetupName = UniqueName(NewGF_NewSetupName, 11, 0)
1814                                else
1815                                        SetDataFolder $saveDF
1816                                        return 0                                                        // ******* EXIT *********
1817                                endif
1818                        endif
1819                else
1820                        DoAlert 1, "The setup name is not a legal name. Fix it up and continue?"
1821                        if (V_flag == 1)
1822                                NewGF_NewSetupName = CleanupName(NewGF_NewSetupName, 1)
1823                                NewGF_NewSetupName = UniqueName(NewGF_NewSetupName, 11, 0)
1824                        endif
1825                endif
1826        endif
1827        DuplicateDataFolder ::NewGlobalFit, $NewGF_NewSetupName
1828        SetDataFolder $NewGF_NewSetupName
1829       
1830        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_ConstraintsCheckBox
1831        Variable/G DoConstraints = V_value
1832        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_WeightingCheckBox
1833        Variable/G DoWeighting = V_value
1834        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_MaskingCheckBox
1835        Variable/G DoMasking = V_value
1836        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoCovarMatrix
1837        Variable/G DoCovarMatrix = V_value
1838        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_CorrelationMatrixCheckBox
1839        Variable/G DoCorelMatrix = V_value
1840        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_MakeFitCurvesCheck
1841        Variable/G MakeFitCurves = V_value
1842        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_AppendResultsCheckbox
1843        Variable/G AppendResults = V_value
1844        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoResidualCheck
1845        Variable/G DoResiduals = V_value
1846        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoDestLogSpacingCheck
1847        Variable/G DoLogSpacing = V_value
1848        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_Quiet
1849        Variable/G DoQuiet = V_value
1850        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_FitProgressGraphCheckBox
1851        Variable/G DoFitProgressGraph = V_value
1852       
1853        KillWaves/Z YCumData, FitY, NewGF_FitFuncNames, NewGF_LinkageMatrix, NewGF_DataSetsList, NewGF_CoefWave
1854        KillWaves/Z NewGF_CoefficientNames, CoefDataSetLinkage, FitFuncList, DataSetPointer, ScratchCoefs, MasterCoefs, EpsilonWave
1855        KillWaves/Z GFWeightWave, GFMaskWave, GFUI_GlobalFitConstraintWave, Res_YCumData, M_Covar, W_sigma, W_ParamConfidenceInterval
1856        KillWaves/Z M_Correlation, fitXCumData, XCumData
1857       
1858        KillVariables/Z V_Flag, V_FitQuitReason, V_FitError, V_FitNumIters, V_numNaNs, V_numINFs, V_npnts, V_nterms, V_nheld
1859        KillVariables/Z V_startRow, V_endRow, V_startCol, V_endCol, V_chisq
1860       
1861        SetDataFolder $saveDF
1862End
1863
1864static Function NewGF_RestoreSetupMenuProc(PU_Struct) : PopupMenuControl
1865        STRUCT WMPopupAction &PU_Struct
1866
1867        if (PU_Struct.eventCode == 2)                   // mouse up
1868                String saveDF = GetDataFolder(1)
1869               
1870                SetDataFolder root:Packages:NewGlobalFit_StoredSetups:$(PU_Struct.popStr)
1871                Variable i = 0
1872                do
1873                        Wave/Z w = WaveRefIndexed("", i, 4)
1874                        if (!WaveExists(w))
1875                                break
1876                        endif
1877                       
1878                        Duplicate/O w, root:Packages:NewGlobalFit:$(NameOfWave(w))
1879                        i += 1
1880                while (1)
1881               
1882                String vars = VariableList("*", ";", 4)
1883                Variable nv = ItemsInList(vars)
1884                for (i = 0; i < nv; i += 1)
1885                        String varname = StringFromList(i, vars)
1886                        NVAR vv = $varname
1887                        Variable/G root:Packages:NewGlobalFit:$varname = vv
1888                endfor
1889               
1890                String strs = StringList("*", ";")
1891                Variable nstr = ItemsInList(strs)
1892                for (i = 0; i < nstr; i += 1)
1893                        String strname = StringFromList(i, strs)
1894                        SVAR ss = $strname
1895                        String/G root:Packages:NewGlobalFit:$strname = ss
1896                endfor
1897               
1898                SetDataFolder root:Packages:NewGlobalFit
1899                NVAR DoConstraints
1900                CheckBox NewGF_ConstraintsCheckBox,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoConstraints
1901                NVAR DoWeighting
1902                CheckBox NewGF_WeightingCheckBox,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoWeighting
1903                NVAR DoMasking
1904                CheckBox NewGF_MaskingCheckBox,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoMasking
1905                NVAR DoCovarMatrix
1906                CheckBox NewGF_DoCovarMatrix,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoCovarMatrix
1907                NVAR DoCorelMatrix
1908                CheckBox NewGF_CorrelationMatrixCheckBox,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoCorelMatrix
1909                NVAR MakeFitCurves
1910                CheckBox NewGF_MakeFitCurvesCheck,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=MakeFitCurves
1911                NVAR AppendResults
1912                CheckBox NewGF_AppendResultsCheckbox,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=AppendResults
1913                NVAR DoResiduals
1914                CheckBox NewGF_DoResidualCheck,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoResiduals
1915                Variable/G DoLogSpacing = NumVarOrDefault("DoLogSpacing", 0)
1916                CheckBox NewGF_DoDestLogSpacingCheck,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoLogSpacing
1917                NVAR DoQuiet
1918                CheckBox NewGF_Quiet,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoQuiet
1919                NVAR DoFitProgressGraph
1920                CheckBox NewGF_FitProgressGraphCheckBox,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoFitProgressGraph
1921                KillVariables/Z DoConstraints, DoWeighting, DoMasking, DoCovarMatrix, DoCorelMatrix, MakeFitCurves, AppendResults, DoResiduals, DoQuiet, DoFitProgressGraph
1922               
1923                SetDataFolder $saveDF
1924        endif
1925End
1926
1927Function NewGF_SetTabControlContent(whichTab)
1928        Variable whichTab
1929       
1930        switch(whichTab)
1931                case 0:
1932                        DefineGuide/W=NewGlobalFitPanel Tab1AreaLeft={FR,25},Tab1AreaRight={FR,800}
1933                        DefineGuide/W=NewGlobalFitPanel Tab0AreaLeft={FL,13},Tab0AreaRight={FR,-10}
1934                        break;
1935                case 1:
1936                        NVAR/Z NewGF_RebuildCoefListNow = root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow
1937                        if (!NVAR_Exists(NewGF_RebuildCoefListNow) || NewGF_RebuildCoefListNow)
1938                                NewGF_RebuildCoefListWave()
1939                        endif
1940                        DefineGuide/W=NewGlobalFitPanel Tab0AreaLeft={FR,25},Tab0AreaRight={FR,800}
1941                        DefineGuide/W=NewGlobalFitPanel Tab1AreaLeft={FL,13},Tab1AreaRight={FR, -10}
1942                        break;
1943        endswitch
1944        NewGF_MoveControls()
1945end
1946
1947static Function NewGF_TabControlProc(TC_Struct)
1948        STRUCT WMTabControlAction &TC_Struct
1949
1950        if (TC_Struct.eventCode == 2)
1951                NewGF_SetTabControlContent(TC_Struct.tab)
1952        endif
1953End
1954
1955static Function isControlOrRightClick(eventMod)
1956        Variable eventMod
1957       
1958        if (CmpStr(IgorInfo(2), "Macintosh") == 0)
1959                if ( (eventMod & 24) == 16)
1960                        return 1
1961                endif
1962        else
1963                if ( (eventMod & 16) == 16)
1964                        return 1
1965                endif
1966        endif
1967       
1968        return 0
1969end
1970
1971//static Function NewGF_DataSetListBoxProc(ctrlName,row,col,event)
1972//      String ctrlName     // name of this control
1973//      Variable row        // row if click in interior, -1 if click in title
1974//      Variable col        // column number
1975//      Variable event      // event code
1976       
1977static Function NewGF_DataSetListBoxProc(LB_Struct)
1978        STRUCT WMListboxAction &LB_Struct
1979       
1980        Variable numcoefs
1981        String funcName
1982       
1983        if (LB_Struct.eventCode == 7)           // finish edit
1984                if (CmpStr(LB_Struct.ctrlName, "NewGF_Tab0CoefList") == 0)
1985                        return 0
1986                endif
1987                       
1988                if (LB_Struct.col == NewGF_DSList_NCoefCol)
1989                        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
1990                        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
1991                        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
1992                        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
1993                        Variable i,j
1994                        Variable numrows = DimSize(ListWave, 0)
1995                        Variable numcols = DimSize(Listwave, 1)
1996               
1997                        numcoefs = str2num(ListWave[LB_Struct.row][LB_Struct.col][0])
1998                        funcName = ListWave[LB_Struct.row][NewGF_DSList_FuncCol][0]
1999                        Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2000                       
2001                        if (NumCoefs > DimSize(CoefListWave, 1)-NewGF_DSList_FirstCoefCol)
2002                                Redimension/N=(-1,NumCoefs+NewGF_DSList_FirstCoefCol, -1) CoefListWave, CoefSelWave
2003                                for (i = 1; i < NumCoefs; i += 1)
2004                                        SetDimLabel 1, i+NewGF_DSList_FirstCoefCol,$("K"+num2str(i)), CoefListWave
2005                                endfor
2006                        endif
2007                        for (i = 0; i < numrows; i += 1)
2008                                if (CmpStr(funcName, ListWave[i][NewGF_DSList_FuncCol][0]) == 0)
2009                                        ListWave[i][NewGF_DSList_NCoefCol][0] = num2str(numCoefs)
2010                                        for (j = 0; j < numCoefs; j += 1)
2011                                                if (!IsLinkText(CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]))               // don't change a LINK specification
2012                                                        CoefListWave[i][NewGF_DSList_FirstCoefCol+j] = "r"+num2istr(i)+":K"+num2istr(j)
2013                                                endif
2014                                        endfor
2015                                endif
2016                        endfor
2017                       
2018                        NewGF_CheckCoefsAndReduceDims()
2019                endif
2020        elseif(LB_Struct.eventCode == 1)                // mouse down
2021                        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2022                       
2023                if (LB_Struct.row == -1)
2024                        if (CmpStr(LB_Struct.ctrlName, "NewGF_Tab0CoefList") == 0)
2025                                Wave SelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2026                        else
2027                                Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2028                        endif
2029                        SelWave[][][0] = SelWave[p][q] & ~1                             // de-select everything to make sure we don't leave something selected in another column
2030                        SelWave[][LB_Struct.col][0] = SelWave[p][LB_Struct.col] | 1                     // select all rows
2031                elseif ( (LB_Struct.row >= 0) && (LB_Struct.row < DimSize(SelWave, 0)) )
2032                        if (CmpStr(LB_Struct.ctrlName, "NewGF_Tab0CoefList") == 0)
2033                                return 0
2034                        endif
2035                       
2036//                      if (GetKeyState(0) == 0)                                                                                // no modifier keys
2037                        if (isControlOrRightClick(LB_Struct.eventMod))                          // right-click or ctrl-click
2038                                switch(LB_Struct.col)
2039                                        case NewGF_DSList_YWaveCol:
2040                                                PopupContextualMenu NewGF_YWaveList(-1)
2041                                                if (V_flag > 0)
2042                                                        Wave w = $S_selection
2043                                                        NewGF_SetYWaveForRowInList(w, $"", LB_Struct.row)
2044                                                        SelWave[LB_Struct.row][LB_Struct.col][0] = 0
2045                                                endif
2046                                                break
2047                                        case NewGF_DSList_XWaveCol:
2048                                                Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2049                                                Wave w = $(ListWave[LB_Struct.row][NewGF_DSList_YWaveCol][1])
2050                                                if (WaveExists(w))
2051                                                        String RowsText = num2str(DimSize(w, 0))
2052                                                        PopupContextualMenu "_calculated_;"+WaveList("*",";","MINROWS:"+RowsText+",MAXROWS:"+RowsText+",DIMS:1,CMPLX:0,TEXT:0,BYTE:0,WORD:0,INTEGER:0")
2053                                                        if (V_flag > 0)
2054                                                                Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2055                                                                Wave/Z w = $S_selection
2056                                                                NewGF_SetXWaveInList(w, LB_Struct.row)
2057                                                                SelWave[LB_Struct.row][LB_Struct.col][0] = 0
2058                                                        endif
2059                                                endif
2060                                                break
2061                                        case NewGF_DSList_FuncCol:
2062                                                PopupContextualMenu NewGF_FitFuncList()
2063                                                if (V_flag > 0)
2064                                                        FuncName = S_selection
2065                                                       
2066                                                        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2067                                                        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2068                                                        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2069                                                        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2070                                                       
2071                                                        String CoefList
2072                                                        NumCoefs = GetNumCoefsAndNamesFromFunction(FuncName, coefList)
2073                                                       
2074                                                        if (numType(NumCoefs) == 0)
2075                                                                if (NumCoefs > DimSize(CoefListWave, 1)-NewGF_DSList_FirstCoefCol)
2076                                                                        Redimension/N=(-1,NumCoefs+NewGF_DSList_FirstCoefCol, -1) CoefListWave, CoefSelWave
2077                                                                        for (i = 1; i < NumCoefs; i += 1)
2078                                                                                SetDimLabel 1, i+NewGF_DSList_FirstCoefCol,$("K"+num2str(i)), CoefListWave
2079                                                                        endfor
2080                                                                endif
2081                                                        endif
2082                                                       
2083                                                        Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2084                                                        ListWave[LB_Struct.row][NewGF_DSList_FuncCol][0] = FuncName
2085                                                        if (numType(NumCoefs) == 0)
2086                                                                ListWave[LB_Struct.row][NewGF_DSList_NCoefCol][0] = num2istr(NumCoefs)
2087                                                                for (j = 0; j < NumCoefs; j += 1)
2088                                                                        String coeftitle = StringFromList(j, coefList)
2089                                                                        if (strlen(coeftitle) == 0)
2090                                                                                coeftitle = "r"+num2istr(LB_Struct.row)+":K"+num2istr(j)
2091                                                                        else
2092                                                                                coeftitle = "r"+num2istr(LB_Struct.row)+":"+coeftitle
2093                                                                        endif
2094                                                                        CoefListWave[LB_Struct.row][NewGF_DSList_FirstCoefCol+j] = coeftitle
2095                                                                endfor
2096                                                                SelWave[LB_Struct.row][NewGF_DSList_NCoefCol][0] = 0
2097                                                        else
2098                                                                SelWave[LB_Struct.row][NewGF_DSList_NCoefCol][0] = 2
2099                                                        endif
2100                                                        for (j = j+NewGF_DSList_FirstCoefCol;j < DimSize(ListWave, 1); j += 1)
2101                                                                CoefListWave[LB_Struct.row][j] = ""
2102                                                        endfor
2103                                                       
2104                                                        NewGF_CheckCoefsAndReduceDims()
2105                                                endif
2106                                                break
2107                                endswitch
2108                        endif
2109                endif
2110        elseif ( (LB_Struct.eventCode == 8) || (LB_Struct.eventCode == 10) )            // vertical scroll or programmatically set top row
2111                String otherCtrl = ""
2112                if (CmpStr(LB_Struct.ctrlName, "NewGF_DataSetsList") == 0)
2113                        otherCtrl = "NewGF_Tab0CoefList"
2114                else
2115                        otherCtrl = "NewGF_DataSetsList"
2116                endif
2117                ControlInfo/W=NewGlobalFitPanel#Tab0ContentPanel $otherCtrl
2118//print LB_Struct.ctrlName, otherCtrl, "event = ", LB_Struct.eventCode, "row = ", LB_Struct.row, "V_startRow = ", V_startRow
2119                if (V_startRow != LB_Struct.row)
2120                        ListBox $otherCtrl win=NewGlobalFitPanel#Tab0ContentPanel,row=LB_Struct.row
2121                        DoUpdate
2122                endif
2123        endif
2124End
2125//xstatic constant NewGF_DSList_YWaveCol = 0
2126//xstatic constant NewGF_DSList_XWaveCol = 1
2127//xstatic constant NewGF_DSList_FuncCol = 2
2128//xstatic constant NewGF_DSList_NCoefCol = 3
2129//xstatic constant NewGF_DSList_FirstCoefCol = 4
2130
2131Function NewGF_AddYWaveMenuProc(PU_Struct)
2132        STRUCT WMPopupAction &PU_Struct
2133
2134        Variable i, nInList
2135       
2136        if (PU_Struct.eventCode == 2)                   // mouse up
2137                strswitch (PU_Struct.popStr)
2138                        case "All From Top Graph":
2139                                String tlist = TraceNameList("", ";", 1)
2140                                String tname
2141                                i = 0
2142                                do
2143                                        tname = StringFromList(i, tlist)
2144                                        if (strlen(tname) == 0)
2145                                                break;
2146                                        endif
2147                                       
2148                                        Wave w = TraceNameToWaveRef("", tname)
2149                                        Wave/Z xw = XWaveRefFromTrace("", tname)
2150                                        if (WaveExists(w) && !NewGF_WaveInListAlready(w))
2151                                                NewGF_AddYWaveToList(w, xw)
2152                                        endif
2153                                        i += 1
2154                                while(1)
2155                                break;
2156                        case "All From Top Table":
2157                                do
2158                                        Wave/Z w = WaveRefIndexed(WinName(0, 2), i, 1)
2159                                        if (!WaveExists(w))
2160                                                break;
2161                                        endif
2162                                       
2163                                        NewGF_AddYWaveToList(w, $"")
2164                                        i += 1
2165                                while (1)
2166                                break;
2167                        default:
2168                                Wave/Z w = $(PU_Struct.popStr)
2169                                if (WaveExists(w) && !NewGF_WaveInListAlready(w))
2170                                        NewGF_AddYWaveToList(w, $"")
2171                                endif
2172                                break;
2173                endswitch
2174        endif
2175       
2176        return 0
2177end
2178
2179static Function NewGF_WaveInListAlready(w)
2180        Wave w
2181       
2182        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2183        Variable i
2184        Variable nrows = DimSize(ListWave, 0)
2185        for (i = 0; i < nrows; i += 1)
2186                Wave/Z rowWave = $(ListWave[i][NewGF_DSList_YWaveCol][1])
2187                if (WaveExists(rowWave) && (CmpStr(ListWave[i][NewGF_DSList_YWaveCol][1], GetWavesDataFolder(w, 2)) == 0))
2188                        return 1
2189                endif
2190        endfor
2191       
2192        return 0
2193end
2194
2195static Function NewGF_AddYWaveToList(w, xw)
2196        Wave w
2197        Wave/Z xw
2198       
2199        if (!NewGF_WaveIsSuitable(w))
2200                return 0
2201        endif
2202       
2203        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2204        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2205        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2206        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2207       
2208        Variable nextRow
2209       
2210        if (DimSize(ListWave, 0) == 1)
2211                if (AllFieldsAreBlank(ListWave, 0))
2212                        nextRow = 0
2213                else
2214                        nextRow = 1
2215                endif
2216        else
2217                nextRow = DimSize(ListWave, 0)
2218        endif
2219       
2220        Redimension/N=(nextRow+1, -1, -1) ListWave, SelWave, CoefListWave, CoefSelWave
2221        SelWave[nextRow] = 0
2222        CoefSelWave[nextRow] = 0
2223        SelWave[nextRow][NewGF_DSList_NCoefCol][0] = 2
2224        ListWave[nextRow] = ""
2225        CoefListWave[nextRow] = ""
2226       
2227        NewGF_SetYWaveForRowInList(w, xw, nextRow)
2228       
2229//      ListWave[nextRow][NewGF_DSList_YWaveCol][0] = NameOfWave(w)
2230//      ListWave[nextRow][NewGF_DSList_YWaveCol][1] = GetWavesDataFolder(w, 2)
2231//      if (WaveExists(xw))
2232//              ListWave[nextRow][NewGF_DSList_XWaveCol][0] = NameOfWave(xw)
2233//              ListWave[nextRow][NewGF_DSList_XWaveCol][1] = GetWavesDataFolder(xw, 2)
2234//      else
2235//              ListWave[nextRow][NewGF_DSList_XWaveCol][0] = "_calculated_"
2236//              ListWave[nextRow][NewGF_DSList_XWaveCol][1] = "_calculated_"
2237//      endif
2238       
2239        Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2240end
2241
2242static Function NewGF_SetYWaveForRowInList(w, xw, row)
2243        Wave/Z w
2244        Wave/Z xw
2245        Variable row
2246       
2247        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2248       
2249        if (WaveExists(w))
2250                ListWave[row][NewGF_DSList_YWaveCol][0] = NameOfWave(w)
2251                ListWave[row][NewGF_DSList_YWaveCol][1] = GetWavesDataFolder(w, 2)
2252        else
2253                ListWave[row][NewGF_DSList_YWaveCol][0] = ""                    // this allows us to clear the data set from a row
2254                ListWave[row][NewGF_DSList_YWaveCol][1] = ""
2255        endif
2256        if (WaveExists(xw))
2257                ListWave[row][NewGF_DSList_XWaveCol][0] = NameOfWave(xw)
2258                ListWave[row][NewGF_DSList_XWaveCol][1] = GetWavesDataFolder(xw, 2)
2259        else
2260                ListWave[row][NewGF_DSList_XWaveCol][0] = "_calculated_"
2261                ListWave[row][NewGF_DSList_XWaveCol][1] = "_calculated_"
2262        endif
2263       
2264        // Whatever happens above, something in the list has changed, so we need to flag the change  for the next time the tab changes
2265        NVAR/Z NewGF_RebuildCoefListNow = root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow
2266        if (!NVAR_Exists(NewGF_RebuildCoefListNow))
2267                Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1
2268        endif
2269        NewGF_RebuildCoefListNow = 1
2270end
2271
2272static Function NewGF_SetDataSetMenuProc(PU_Struct)
2273        STRUCT WMPopupAction &PU_Struct
2274
2275        Variable i, j, nInList
2276       
2277        if (PU_Struct.eventCode == 2)                   // mouse up
2278                Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2279                Variable numRows = DimSize(SelWave, 0)
2280
2281                strswitch (PU_Struct.popStr)
2282                        case "From Top Graph":
2283                                String tlist = TraceNameList("", ";", 1)
2284                                String tname
2285                                i = 0; j = 0
2286                                for (j = 0; j < numRows; j += 1)
2287                                        if ( (SelWave[j][NewGF_DSList_YWaveCol] & 9) != 0)
2288                                                NewGF_SetYWaveForRowInList($"", $"", j)
2289                                        endif
2290                                endfor
2291                                for (j = 0; j < numRows; j += 1)
2292                                        if ( (SelWave[j][NewGF_DSList_YWaveCol] & 9) != 0)
2293                                                tname = StringFromList(i, tlist)
2294                                                if (strlen(tname) == 0)
2295                                                        break;
2296                                                endif
2297                                               
2298                                                Wave w = TraceNameToWaveRef("", tname)
2299                                                Wave/Z xw = XWaveRefFromTrace("", tname)
2300                                                if (WaveExists(w))
2301                                                        if  (!NewGF_WaveInListAlready(w))
2302                                                                NewGF_SetYWaveForRowInList(w, xw, j)
2303                                                        else
2304                                                                j -= 1          // we didn't use this row, so counteract the increment for loop (??)
2305                                                        endif
2306                                                endif
2307                                                i += 1
2308                                        endif
2309                                endfor
2310                                break;
2311                        case "From Top Table":
2312                                i = 0; j = 0
2313                                for (j = 0; j < numRows; j += 1)
2314                                        if ( (SelWave[j][NewGF_DSList_YWaveCol] & 9) != 0)
2315                                                NewGF_SetYWaveForRowInList($"", $"", j)
2316                                        endif
2317                                endfor
2318                                for (j = 0; j < numRows; j += 1)
2319                                        if ( (SelWave[j][NewGF_DSList_YWaveCol] & 9) != 0)
2320                                                Wave w = WaveRefIndexed(WinName(0, 2), i, 1)
2321                                                if (!WaveExists(w))
2322                                                        break;
2323                                                endif
2324                                               
2325                                                NewGF_SetYWaveForRowInList(w, $"", j)
2326                                                i += 1
2327                                        endif
2328                                endfor
2329                                break;
2330                        default:
2331                                Wave/Z w = $(PU_Struct.popStr)
2332                                if (WaveExists(w) && !NewGF_WaveInListAlready(w))
2333                                        for (j = 0; j < numRows; j += 1)
2334                                                if ( (SelWave[j][NewGF_DSList_YWaveCol] & 9) != 0)
2335                                                        NewGF_SetYWaveForRowInList($"", $"", j)
2336                                                        NewGF_SetYWaveForRowInList(w, $"", j)
2337                                                        break                           // a data set should appear in the list only once
2338                                                endif
2339                                        endfor
2340                                endif
2341                                break;
2342                endswitch
2343        endif
2344       
2345        return 0
2346End
2347
2348Function NewGF_SetXWaveInList(w, row)
2349        Wave/Z w
2350        Variable row
2351       
2352        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2353        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2354       
2355        if (WaveExists(w))
2356                Wave/Z yWave = $(ListWave[row][NewGF_DSList_YWaveCol][1])
2357                if (WaveExists(yWave))
2358                        if (DimSize(yWave, 0) != DimSize(w, 0))
2359                                DoAlert 0, "The wave "+NameOfWave(yWave)+"in row "+num2istr(row)+" has different number of point from the X wave "+NameOfWave(w)
2360                                return -1
2361                        endif
2362                endif
2363               
2364                ListWave[row][NewGF_DSList_XWaveCol][0] = NameOfWave(w)
2365                ListWave[row][NewGF_DSList_XWaveCol][1] = GetWavesDataFolder(w, 2)
2366        else
2367                ListWave[row][NewGF_DSList_XWaveCol][0] = "_calculated_"
2368                ListWave[row][NewGF_DSList_XWaveCol][1] = "_calculated_"
2369        endif
2370       
2371        // Whatever happens above, something in the list has changed, so we need to flag the change  for the next time the tab changes
2372        NVAR/Z NewGF_RebuildCoefListNow = root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow
2373        if (!NVAR_Exists(NewGF_RebuildCoefListNow))
2374                Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1
2375        endif
2376        NewGF_RebuildCoefListNow = 1
2377end
2378
2379static Function AllFieldsAreBlank(w, row)
2380        Wave/T w
2381        Variable row
2382       
2383        Variable i
2384        Variable lastRow = DimSize(w, 1)
2385        for (i  = 0; i < lastRow; i += 1)
2386                if (strlen(w[row][i][0]) != 0)
2387                        return 0
2388                endif
2389        endfor
2390       
2391        return 1
2392end
2393
2394static Function NewGF_WaveIsSuitable(w)
2395        Wave w
2396       
2397        String wname = NameOfWave(w)
2398       
2399        if (CmpStr(wname[0,3], "fit_") == 0)
2400                return 0
2401        endif
2402        if (CmpStr(wname[0,3], "res_") == 0)
2403                return 0
2404        endif
2405        if (CmpStr(wname[0,4], "GFit_") == 0)
2406                return 0
2407        endif
2408        if (CmpStr(wname[0,4], "GRes_") == 0)
2409                return 0
2410        endif
2411       
2412        return 1
2413end
2414
2415static Function NewGF_SetXWaveMenuProc(PU_Struct)
2416        STRUCT WMPopupAction &PU_Struct
2417
2418//For a PopupMenu control, the WMPopupAction structure has members as described in the following table:
2419//WMPopupAction Structure Members       
2420//Member        Description
2421//char ctrlName[MAX_OBJ_NAME+1] Control name.
2422//char win[MAX_WIN_PATH+1]      Host (sub)window.
2423//STRUCT Rect winRect   Local coordinates of host window.
2424//STRUCT Rect ctrlRect  Enclosing rectangle of the control.
2425//STRUCT Point mouseLoc Mouse location.
2426//Int32 eventCode       Event that caused the procedure to execute. Main event is mouse up=2.
2427//String userdata       Primary (unnamed) user data. If this changes, it is written back automatically.
2428//Int32 popNum  Item number currently selected (1-based).
2429//char popStr[MAXCMDLEN]        Contents of current popup item.
2430
2431        Variable i, nInList, waveindex
2432
2433        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2434        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2435        Variable numListrows = DimSize(ListWave, 0)
2436       
2437        if (PU_Struct.eventCode == 2)                   // mouse up
2438                strswitch (PU_Struct.popStr)
2439                        case "Top Table to List":
2440                                for (i = 0; i < numListrows; i += 1)
2441                                        Wave/Z w = WaveRefIndexed(WinName(0, 2), i, 1)
2442                                        if (!WaveExists(w))
2443                                                break;
2444                                        endif
2445                                       
2446                                        if (NewGF_SetXWaveInList(w, i))
2447                                                break
2448                                        endif
2449                                endfor
2450                                break;
2451                        case "Top Table to Selection":
2452                                waveindex = 0
2453                                for (i = 0; i < numListrows; i += 1)
2454                                        if (SelWave[i][NewGF_DSList_XWaveCol][0] & 9)
2455                                                Wave/Z w = WaveRefIndexed(WinName(0, 2), waveindex, 1)
2456                                                if (!WaveExists(w))
2457                                                        break;
2458                                                endif
2459                                                if (NewGF_SetXWaveInList(w, i))
2460                                                        break
2461                                                endif
2462                                                waveindex += 1
2463                                        endif
2464                                endfor
2465                                break;
2466                        case "Set All to _calculated_":
2467                                for (i = 0; i < numListrows; i += 1)
2468                                        ListWave[i][NewGF_DSList_XWaveCol] = "_calculated_"
2469                                endfor
2470                                break;
2471                        case "Set Selection to _calculated_":
2472                                for (i = 0; i < numListrows; i += 1)
2473                                        if (SelWave[i][NewGF_DSList_XWaveCol][0] & 9)
2474                                                ListWave[i][NewGF_DSList_XWaveCol] = "_calculated_"
2475                                        endif
2476                                endfor
2477                                break;
2478                        default:
2479                                Wave/Z w = $PU_Struct.popStr
2480                                if (WaveExists(w))
2481                                        for (i = 0; i < numListrows; i += 1)
2482                                                if (SelWave[i][NewGF_DSList_XWaveCol][0] & 9)
2483                                                        NewGF_SetXWaveInList(w, i)
2484                                                        //break
2485                                                endif
2486                                        endfor
2487                                endif
2488                                break;
2489                endswitch
2490        endif
2491       
2492        return 0
2493end
2494
2495static Function NewGF_RemoveDataSetsProc(PU_Struct)
2496        STRUCT WMPopupAction &PU_Struct
2497
2498        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2499        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2500        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2501        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2502       
2503        Variable i,j
2504        Variable ncols = DimSize(ListWave, 1)
2505        Variable nrows = DimSize(ListWave, 0)
2506       
2507        if (PU_Struct.eventCode == 2)                   // mouse up
2508                strswitch (PU_Struct.popStr)
2509                        case "Remove All":
2510                                Redimension/N=(1, 4, -1) ListWave, SelWave
2511                                Redimension/N=(1, 1, -1) CoefListWave, CoefSelWave
2512                                ListWave = ""
2513                                CoefListWave = ""
2514                                SelWave = 0
2515                                CoefSelWave = 0
2516                                Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2517                                break
2518                        case "Remove Selection":
2519                                for (i = nrows-1; i >= 0; i -= 1)
2520                                        for (j = 0; j < ncols; j += 1)
2521                                                if (SelWave[i][j][0] & 9)
2522                                                        DeletePoints i, 1, ListWave, SelWave, CoefListWave, CoefSelWave
2523                                                        Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2524                                                        break
2525                                                endif
2526                                        endfor
2527                                endfor
2528                                break
2529                        default:
2530                                for (i = 0; i < nrows; i += 1)
2531                                        if (CmpStr(PU_Struct.popStr, ListWave[i][NewGF_DSList_YWaveCol][0]) == 0)
2532                                                DeletePoints i, 1, ListWave, SelWave, CoefListWave, CoefSelWave
2533                                                Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2534                                                break
2535                                        endif
2536                                endfor
2537                                break
2538                endswitch
2539        endif
2540end
2541
2542Function NewGF_FitFuncSetSelecRadioProc(ctrlName,checked) : CheckBoxControl
2543        String ctrlName
2544        Variable checked
2545
2546        Variable SetSelect = (CmpStr(ctrlName, "NewGF_FitFuncSetSelectionRadio") == 0) ^ checked
2547       
2548        CheckBox NewGF_FitFuncSetSelectionRadio, win=NewGlobalFitPanel#Tab0ContentPanel, value = SetSelect
2549       
2550        CheckBox NewGF_FitFuncSetAllRadio, win=NewGlobalFitPanel#Tab0ContentPanel, value = !SetSelect
2551End
2552
2553static Function NewGF_CheckCoefsAndReduceDims()
2554        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2555        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2556        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2557        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2558
2559        Variable i
2560        Variable numListRows = DimSize(ListWave, 0)
2561        Variable maxCoefs = 0
2562       
2563        // collect the maximum number of coefficients from the # Coefs column
2564        for (i = 0; i < numListRows; i += 1)
2565                Variable numCoefs = str2num(ListWave[i][NewGF_DSList_NCoefCol])
2566                maxCoefs = max(maxCoefs, numCoefs)
2567        endfor
2568       
2569        if (maxCoefs < DimSize(CoefListWave, 1)-NewGF_DSList_FirstCoefCol)
2570                Variable needCols = maxCoefs + NewGF_DSList_FirstCoefCol
2571                DeletePoints/M=1 needCols, DimSize(CoefListWave, 1)-needCols, CoefListWave, CoefSelWave
2572        endif
2573end
2574
2575Function NewGF_SetFuncMenuProc(PU_Struct)
2576        STRUCT WMPopupAction &PU_Struct
2577
2578        if (PU_Struct.eventCode == 2)                   // mouse up
2579       
2580                Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2581                Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2582                Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2583                Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2584               
2585                Variable numListrows = DimSize(ListWave, 0)
2586                String CoefList
2587                Variable NumCoefs = GetNumCoefsAndNamesFromFunction(PU_Struct.popStr, coefList)
2588                Variable i, j
2589               
2590//              ControlInfo NewGF_FitFuncSetSelectionRadio
2591//              Variable SetSelection = V_value
2592               
2593                if (numType(NumCoefs) == 0)
2594                        if (NumCoefs > DimSize(CoefListWave, 1)-NewGF_DSList_FirstCoefCol)
2595                                Redimension/N=(-1,NumCoefs+NewGF_DSList_FirstCoefCol, -1) CoefListWave, CoefSelWave
2596                                for (i = 1; i < NumCoefs; i += 1)
2597                                        SetDimLabel 1, i+NewGF_DSList_FirstCoefCol,$("K"+num2str(i)), CoefListWave
2598                                endfor
2599                        endif
2600                endif
2601               
2602                for (i = 0; i < numListRows; i += 1)
2603                        if ((SelWave[i][NewGF_DSList_FuncCol][0] & 9) == 0)
2604                                continue                // skip unselected rows
2605                        endif
2606                       
2607                        Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2608                        ListWave[i][NewGF_DSList_FuncCol][0] = PU_Struct.popStr
2609                        if (numType(NumCoefs) == 0)
2610                                ListWave[i][NewGF_DSList_NCoefCol][0] = num2istr(NumCoefs)
2611                                for (j = 0; j < NumCoefs; j += 1)
2612                                        String coeftitle = StringFromList(j, coefList)
2613                                        if (strlen(coeftitle) == 0)
2614                                                coeftitle = "r"+num2istr(i)+":K"+num2istr(j)
2615                                        else
2616                                                coeftitle = "r"+num2istr(i)+":"+coeftitle
2617                                        endif
2618                                        CoefListWave[i][NewGF_DSList_FirstCoefCol+j] = coeftitle
2619                                endfor
2620                                SelWave[i][NewGF_DSList_NCoefCol][0] = 0
2621                        else
2622                                SelWave[i][NewGF_DSList_NCoefCol][0] = 2
2623                        endif
2624                endfor
2625               
2626                NewGF_CheckCoefsAndReduceDims()
2627        endif
2628end
2629
2630Function NewGF_LinkCoefsButtonProc(ctrlName) : ButtonControl
2631        String ctrlName
2632
2633        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2634        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2635        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2636        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2637       
2638        Variable listRows = DimSize(CoefListWave, 0)
2639        Variable listCols = DimSize(CoefListWave, 1)
2640        Variable i,j
2641        String linkCellText = ""
2642        Variable linkrow, linkcol
2643        Variable lastCol
2644        Variable colorIndex = 1
2645
2646        // scan for link color indices in order to set the color index to use this time to the first free color
2647        do
2648                Variable startOver = 0
2649                for (i = 0; i < listRows; i += 1)
2650                        for (j = NewGF_DSList_FirstCoefCol; j < listCols; j += 1)
2651                                if (CoefSelWave[i][j][%backColors] == colorIndex)
2652                                        colorIndex += 1
2653                                        startOver = 1
2654                                        break;
2655                                endif
2656                        endfor
2657                        if (startOver)
2658                                break;
2659                        endif
2660                endfor
2661        while (startOver)
2662       
2663        // find the first cell in the selection to record the link row and column, and to set the color index if it is already linked.
2664        for (i = 0; i < listRows; i += 1)
2665                lastCol = NewGF_DSList_FirstCoefCol + str2num(ListWave[i][NewGF_DSList_NCoefCol][0])
2666                for (j = NewGF_DSList_FirstCoefCol; j < lastCol; j += 1)
2667                        if (CoefSelWave[i][j][0] & 9)
2668                                linkCellText = CoefListWave[i][j][0]
2669                                linkrow = i
2670                                linkcol = j
2671                                if (CoefSelWave[i][j][%backColors] != 0)
2672                                        colorIndex = CoefSelWave[i][j][%backColors]
2673                                endif
2674                                break;
2675                        endif
2676                endfor
2677                if (strlen(linkCellText) > 0)
2678                        break;
2679                endif
2680        endfor
2681        // if the first cell in the selection is a link, we want to set the link text to be the original, not derived from the current first selection cell.
2682        if (IsLinkText(linkCellText))
2683                linkCellText = linkCellText[5, strlen(linkCellText)-1]
2684        endif
2685        CoefSelWave[linkrow][linkcol][0] = 0            // de-select the first selected cell
2686       
2687        Wave/T Tab1CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
2688        Wave Tab1CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
2689
2690        Variable accumulatedGuess = 0
2691        Variable numAccumulatedGuesses = 0
2692        Variable linkGuessListIndex = CoefIndexFromTab0CoefRowAndCol(linkrow, linkcol)
2693        Variable initGuess = str2num(Tab1CoefListWave[linkGuessListIndex][2])
2694        if (numtype(initGuess) == 0)
2695                accumulatedGuess += initGuess
2696                numAccumulatedGuesses += 1
2697        endif
2698        string listOfLinkedRows = num2str(linkGuessListIndex)+";"
2699        string tab1LinkCellText = Tab1CoefListWave[linkGuessListIndex][1]
2700       
2701        // now scan from the cell after the first selected cell looking for selected cells to link to the first one
2702        j = linkcol+1
2703        for (i = linkrow; i < listRows; i += 1)
2704                lastCol = NewGF_DSList_FirstCoefCol + str2num(ListWave[i][NewGF_DSList_NCoefCol][0])
2705                do
2706                        if (j >= listCols)
2707                                break
2708                        endif
2709                        if (CoefSelWave[i][j][0] & 9)
2710                                Variable nCoefs = str2num(ListWave[i][NewGF_DSList_NCoefCol][0])
2711                                if (j >= nCoefs)
2712                                        CoefSelWave[i][j][0] = 0                // un-select this cell
2713                                        break                   // this column isn't used for in this row because this function has fewer coefficients than the maximum
2714                                endif
2715                       
2716                                CoefListWave[i][j][0] = "LINK:"+linkCellText
2717                                CoefSelWave[i][j][%backColors] = colorIndex
2718                                CoefSelWave[linkRow][linkCol][%backColors] = colorIndex                                                 // don't want to set the color of this cell unless another cell is linked to it
2719                                CoefSelWave[i][j][0] = 0
2720                                linkGuessListIndex = CoefIndexFromTab0CoefRowAndCol(i, j)
2721                                initGuess = str2num(Tab1CoefListWave[linkGuessListIndex][2])
2722                                if (numtype(initGuess) == 0)
2723                                        accumulatedGuess += initGuess
2724                                        numAccumulatedGuesses += 1
2725                                endif
2726                                Tab1CoefListWave[linkGuessListIndex][1] = "LINK:"+tab1LinkCellText
2727                                Tab1CoefSelWave[linkGuessListIndex][1] = 0
2728                                Tab1CoefSelWave[linkGuessListIndex][2] = 0
2729                                Tab1CoefSelWave[linkGuessListIndex][3] = 0                      // no more checkbox for holding
2730                                listOfLinkedRows += num2str(linkGuessListIndex)+";"
2731//                              Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2732                        endif
2733                                               
2734                        j += 1
2735                while(1)
2736                j = NewGF_DSList_FirstCoefCol
2737        endfor
2738       
2739        // finally, install the average initial guess into all the linked rows in the tab1 coefficient control list
2740        if (numAccumulatedGuesses > 0)
2741                accumulatedGuess /= numAccumulatedGuesses
2742                Variable endindex = ItemsInList(listOfLinkedRows)
2743                for (i = 0; i < endindex; i += 1)
2744                        Tab1CoefListWave[str2num(StringFromList(i, listOfLinkedRows))][2] = num2str(accumulatedGuess)
2745                endfor
2746        endif
2747End
2748
2749// returns the row in the coefficient guess list (tab 1) for a given row and column in the coefficient list on tab 0
2750static Function CoefIndexFromTab0CoefRowAndCol(row, col)
2751        Variable row, col
2752       
2753        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2754
2755        Variable i, j
2756        col -= NewGF_DSList_FirstCoefCol
2757       
2758        Variable coefListIndex = 0
2759        for (i = 0; i < row; i += 1)
2760                coefListIndex += str2num(ListWave[i][NewGF_DSList_NCoefCol][0])
2761        endfor
2762        coefListIndex += col
2763       
2764        return coefListIndex
2765end
2766
2767Function NewGF_UnLinkCoefsButtonProc(ctrlName) : ButtonControl
2768        String ctrlName
2769
2770
2771        Wave/T DataSetListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2772//      Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2773        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2774        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2775
2776        Wave/T Tab1CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
2777        Wave Tab1CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
2778       
2779        Variable listRows = DimSize(CoefListWave, 0)
2780        Variable listCols = DimSize(CoefListWave, 1)
2781        Variable i,j
2782       
2783        for (i = 0; i < listRows; i += 1)
2784                for (j = NewGF_DSList_FirstCoefCol; j < listCols; j += 1)
2785                        if (CoefSelWave[i][j][0] & 9)
2786                                Variable nCoefs = str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
2787                                if (j >= nCoefs)
2788                                        CoefSelWave[i][j][] = 0         // sets color to white AND un-selects
2789                                        continue                        // this column isn't used for in this row because this function has fewer coefficients than the maximum
2790                                endif
2791                                CoefListWave[i][j][0] = CoefListWave[i][j][1]
2792                                CoefSelWave[i][j][] = 0         // sets color to white AND un-selects
2793                                Variable linkGuessListIndex = CoefIndexFromTab0CoefRowAndCol(i, j)
2794                                Tab1CoefSelWave[linkGuessListIndex][1] = 2
2795                                Tab1CoefSelWave[linkGuessListIndex][2] = 2
2796                                Tab1CoefSelWave[linkGuessListIndex][3] = 0x20           // checkbox
2797                                String coefName = CoefNameFromListText(CoefListWave[i][NewGF_DSList_FirstCoefCol + j][1])
2798                                Tab1CoefListWave[linkGuessListIndex][1] = coefName+"["+DataSetListWave[i][NewGF_DSList_FuncCol][0]+"]["+DataSetListWave[i][NewGF_DSList_YWaveCol][1]+"]"        // last part is full path to Y wave
2799
2800//                              Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2801                        endif
2802                endfor
2803        endfor
2804End
2805
2806static Function NewGF_SelectAllCoefMenuProc(PU_Struct) : PopupMenuControl
2807        STRUCT WMPopupAction &PU_Struct
2808
2809        if (PU_Struct.eventCode == 2)                   // mouse up
2810                Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2811//              Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2812                Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2813                Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2814                Variable i,j
2815                Variable numRows = DimSize(CoefListWave, 0)
2816               
2817                if (CmpStr(PU_Struct.ctrlName, "NewGF_SelectAllCoefMenu") == 0)
2818                        CoefSelWave[][][0] = CoefSelWave[p][q][0] & ~9          // clear selection if we're not adding to the selection
2819                endif
2820               
2821                String FuncName = FuncNameFromFuncAndCoef(PU_Struct.popstr)
2822                String CoefName = CoefNameFromListText(PU_Struct.popstr)
2823                for (i = 0; i < numRows; i += 1)
2824                        if (CmpStr(FuncName, ListWave[i][NewGF_DSList_FuncCol][0]) == 0)
2825                                Variable nc = str2num(ListWave[i][NewGF_DSList_NCoefCol][0])
2826                                for (j = 0; j < nc; j += 1)
2827                                        if (CmpStr(CoefName, CoefNameFromListText(CoefListWave[i][NewGF_DSList_FirstCoefCol + j][0])) == 0)
2828                                                CoefSelWave[i][NewGF_DSList_FirstCoefCol + j][0] = CoefSelWave[i][NewGF_DSList_FirstCoefCol + j][0] | 1
2829                                        endif
2830                                endfor
2831                        endif
2832                endfor
2833        endif
2834End
2835
2836
2837static Function/S CoefNameFromListText(listText)
2838        String listText
2839       
2840        Variable colonPos = strsearch(listText, ":", inf, 1)            // search backwards
2841        return listText[colonPos+1, strlen(listText)-1]
2842end
2843
2844static Function/S FuncNameFromFuncAndCoef(theText)
2845        String theText
2846       
2847        Variable colonpos = strsearch(theText, ":", 0)
2848        return theText[0, colonPos-1]
2849end
2850
2851static Function/S NewGF_ListFunctionsAndCoefs()
2852
2853        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2854        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2855        Variable i, j
2856        Variable numRows = DimSize(ListWave, 0)
2857        String theList = ""
2858       
2859        for (i = 0; i < numRows; i += 1)
2860                Variable nCoefs = str2num(ListWave[i][NewGF_DSList_NCoefCol][0])
2861                String FuncName = ListWave[i][NewGF_DSList_FuncCol][0]
2862                for (j = 0; j < nCoefs; j += 1)
2863                        Variable coefIndex = j + NewGF_DSList_FirstCoefCol
2864                        String coefText = CoefListWave[i][coefIndex][0]
2865                        if (!IsLinkText(coefText))
2866                                String theItem = FuncName+":"+CoefNameFromListText(coefText)
2867                                if (WhichListItem(theItem, theList) < 0)
2868                                        theList += theItem+";"
2869                                endif
2870                        endif
2871                endfor
2872        endfor
2873       
2874        return theList
2875end
2876
2877static Function IsWhiteSpaceChar(thechar)
2878        Variable thechar
2879       
2880        Variable spChar = char2num(" ")
2881        Variable tabChar = char2num("\t")
2882
2883        if ( (thechar == spChar) || (thechar == tabChar) )
2884                return 1
2885        else
2886                return 0
2887        endif
2888end
2889
2890static Function IsEndLine(theLine)
2891        String theLine
2892       
2893        Variable i = 0
2894        Variable linelength = strlen(theLine)
2895       
2896        for (i = 0; i < linelength; i += 1)
2897                Variable thechar = char2num(theLine[i])
2898                if (!IsWhiteSpaceChar(thechar))
2899                        break
2900                endif
2901        endfor
2902        if (i == linelength)
2903                return 0
2904        endif
2905        return CmpStr(theLine[i, i+2], "end") == 0
2906end
2907
2908static Function GetNumCoefsAndNamesFromFunction(funcName, coefList)
2909        String funcName
2910        String &coefList
2911       
2912        Variable i
2913        Variable numCoefs
2914        String funcCode = ProcedureText(funcName )
2915       
2916        coefList = ""
2917       
2918        if (strlen(funcCode) == 0)              // an XOP function?
2919                numCoefs = NaN
2920        else
2921                i=0
2922                Variable commentPos
2923                do
2924                        String aLine = StringFromList(i, funcCode, "\r")
2925                        if (IsEndLine(aLine))
2926                                numCoefs = NaN
2927                                break
2928                        endif
2929                        commentPos = strsearch(aLine, "//CurveFitDialog/ Coefficients", 0 , 2)
2930                        if (commentPos >= 0)            // 2 means ignore case
2931                                sscanf aLine[commentPos, inf], "//CurveFitDialog/ Coefficients %d", numCoefs
2932                                i += 1
2933                                break
2934                        endif
2935                        i += 1
2936                while (1)
2937               
2938                if (numType(numCoefs) == 0)
2939                        do
2940                                aLine = StringFromList(i, funcCode, "\r")
2941                                if (IsEndLine(aLine))
2942                                        break
2943                                endif
2944                                commentPos = strsearch(aLine, "//CurveFitDialog/ w[", 0 , 2)
2945                                if (commentPos >= 0)            // 2 means ignore case
2946                                        Variable equalPos = strsearch(aLine[commentPos, inf], "=", 0) + commentPos
2947                                        if (equalPos > 0)
2948                                                equalPos += 1
2949                                                Variable spChar = char2num(" ")
2950                                                Variable tabChar = char2num("\t")
2951                                                do
2952                                                        Variable char = char2num(aLine[equalPos])
2953                                                        if ( (char == spChar) || (char == tabChar) )
2954                                                                equalPos += 1
2955                                                        else
2956                                                                string name
2957                                                                sscanf aLine[equalPos, inf], "%s", name
2958                                                                coefList += name+";"
2959                                                                break
2960                                                        endif
2961                                                while(1)
2962                                        endif
2963                                endif
2964                                i += 1
2965                        while (1)
2966                endif
2967        endif
2968       
2969        return numCoefs
2970end
2971
2972Function/S NewGF_YWaveList(UseAllWord)
2973        Variable UseAllWord                     // 0: "From Top Graph", 1: "All From Top Graph", -1: Don't include top graph and top table options
2974
2975        if (UseAllWord == 1)
2976                String theList = "All From Top Graph;All From Top Table;-;"
2977        elseif (UseAllWord == -1)
2978                theList = ""
2979        else
2980                theList = "From Top Graph;From Top Table;-;"
2981        endif
2982        theList += WaveList("*", ";", "DIMS:1,CMPLX:0,TEXT:0,BYTE:0,WORD:0,INTEGER:0")
2983        return theList
2984end
2985
2986Function/S NewGF_XWaveList()
2987
2988        String theList = "Top Table to List;Top Table to Selection;Set All to _calculated_;Set Selection to _calculated_;-;"
2989        theList += WaveList("*", ";", "DIMS:1,CMPLX:0,TEXT:0,BYTE:0,WORD:0,INTEGER:0")
2990        return theList
2991end
2992
2993Function/S NewGF_RemoveMenuList()
2994
2995        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2996
2997        String theList = "Remove All;Remove Selection;-;"
2998        Variable i
2999        Variable nrows = DimSize(ListWave, 0)
3000        for (i = 0; i < nrows; i += 1)
3001                theList += (ListWave[i][NewGF_DSList_YWaveCol][0])+";"
3002        endfor
3003       
3004        return theList
3005end
3006
3007//SRK change to exclude XFuncs, my template, and f* functions
3008//
3009Function/S NewGF_FitFuncList()
3010
3011        string theList="", UserFuncs, XFuncs,tmp
3012       
3013        string options = "KIND:10"
3014//      ControlInfo/W=GlobalFitPanel RequireFitFuncCheckbox
3015//      if (V_value)
3016                options += ",SUBTYPE:FitFunc"
3017//      endif
3018        options += ",NINDVARS:1"
3019       
3020        UserFuncs = FunctionList("*", ";",options)
3021        UserFuncs = RemoveFromList("GFFitFuncTemplate", UserFuncs)
3022        UserFuncs = RemoveFromList("GFFitAllAtOnceTemplate", UserFuncs)
3023        UserFuncs = RemoveFromList("NewGlblFitFunc", UserFuncs)
3024        UserFuncs = RemoveFromList("NewGlblFitFuncAllAtOnce", UserFuncs)
3025        UserFuncs = RemoveFromList("GlobalFitFunc", UserFuncs)
3026        UserFuncs = RemoveFromList("GlobalFitAllAtOnce", UserFuncs)
3027        //SRK - remove my template from the list
3028        UserFuncs = RemoveFromList("GFFitAAOStructTemplate", UserFuncs)
3029        tmp = FunctionList("f*",";","NPARAMS:2")                //point calculations
3030        UserFuncs = RemoveFromList(tmp, UserFuncs  ,";")
3031       
3032        tmp = FunctionList("fSmear*",";","NPARAMS:3")           //smeared dependency calculations
3033        UserFuncs = RemoveFromList(tmp, UserFuncs  ,";")
3034        //eSRK
3035
3036//SRK
3037//      XFuncs = FunctionList("*", ";", "KIND:12")
3038        XFuncs = ""
3039//eSRK
3040       
3041        if (strlen(UserFuncs) > 0)
3042                theList +=  "\\M1(   User-defined functions:;"
3043                theList += UserFuncs
3044        endif
3045        if (strlen(XFuncs) > 0)
3046                theList += "\\M1(   External Functions:;"
3047                theList += XFuncs
3048        endif
3049       
3050        if (strlen(theList) == 0)
3051                theList = "\\M1(No Fit Functions"
3052        endif
3053       
3054        //SRK
3055        theList = SortList(theList)
3056        //eSRK
3057        return theList
3058end
3059
3060static Function NewGF_RebuildCoefListWave()
3061
3062        Wave/T DataSetListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3063        Wave/T Tab0CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
3064        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
3065        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
3066       
3067        Variable DSListRows = DimSize(DataSetListWave, 0)
3068        Variable i, j, k
3069        Variable numUnlinkedCoefs = 0
3070        Variable totalCoefs = 0
3071        Variable nc
3072        Variable coefColonPos
3073        Variable colonPos
3074        Variable linkRow
3075       
3076        // count total number of coefficient taking into account linked coefficients
3077        for (i = 0; i < DSListRows; i += 1)
3078                totalCoefs += str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
3079        endfor
3080       
3081        if (numtype(totalCoefs) != 0)
3082                return 0                                                // ****** EXIT ******
3083        endif
3084       
3085        Redimension/N=(totalCoefs, -1, -1) CoefListWave, CoefSelWave
3086        CoefListWave[][2] = ""                  // clear out any initial guesses that might be left over from previous incarnations
3087        CoefSelWave[][3] = 0x20                 // make the new rows have checkboxes in the Hold column
3088        CoefListWave[][3] = ""                  // make the checkboxes have no label
3089        CoefSelWave[][1] = 2                    // make the name column editable
3090        CoefSelWave[][2] = 2                    // make the initial guess column editable
3091        CoefSelWave[][4] = 2                    // make the epsilon column editable
3092        CoefListWave[][4] = "1e-6"              // a reasonable value for epsilon
3093       
3094        Variable coefIndex = 0
3095        for (i = 0; i < DSListRows; i += 1)
3096                nc = str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
3097                for (j = 0; j < nc; j += 1)
3098                        CoefListWave[coefIndex][0] = DataSetListWave[i][NewGF_DSList_YWaveCol][1]                       // use the full path here
3099                        String coefName = CoefNameFromListText(Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol + j][1])
3100                        if (IsLinkText(Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]))
3101                                Variable linkIndex = NewGF_CoefRowForLink(Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0])
3102                                CoefListWave[coefIndex][1] = "LINK:"+CoefListWave[linkIndex][1]
3103                                CoefListWave[coefIndex][2] = CoefListWave[linkIndex][2]
3104                                CoefSelWave[coefIndex][1,] = 0          // not editable- this is a coefficient linked to another
3105                        else
3106                                CoefListWave[coefIndex][1] = coefName+"["+DataSetListWave[i][NewGF_DSList_FuncCol][0]+"]["+DataSetListWave[i][NewGF_DSList_YWaveCol][1]+"]"     // last part is full path to Y wave
3107//                              CoefListWave[coefIndex][1] = DataSetListWave[i][NewGF_DSList_FuncCol][0]+":"+coefText
3108                        endif
3109                        coefIndex += 1
3110                endfor
3111        endfor 
3112       
3113        Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 0
3114end
3115
3116static Function NewGF_CoefListBoxProc(ctrlName,row,col,event) : ListBoxControl
3117        String ctrlName     // name of this control
3118        Variable row        // row if click in interior, -1 if click in title
3119        Variable col        // column number
3120        Variable event      // event code
3121       
3122        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
3123        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
3124        Wave/T DataSetListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3125        Wave/T Tab0CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
3126
3127        Variable DSListRows = DimSize(DataSetListWave, 0)
3128        Variable i,j
3129        Variable coefIndex = 0
3130        Variable selectionExists
3131        String newName
3132        Variable numRowsNeeded
3133       
3134        // if a coefficient name has been changed, we need to track down any linked coefficients and change them, too.
3135        if ( (event == 7) || (event == 2) )             // finish edit
3136                if ( (col >= 1) || (col <= 4) )         // edited a name, initial guess, hold, or epsilon
3137                        if ( (event == 2) && (col != 3) )
3138                                return 0
3139                        endif
3140                        for (i = 0; i <         DSListRows; i += 1)
3141                                Variable nc = str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
3142                                for (j = 0; j < nc; j += 1)
3143                                        if (IsLinkText(Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]))
3144                                                if (NewGF_CoefListRowForLink(Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]) == row)
3145                                                        switch (col)
3146                                                                case 1:
3147                                                                        CoefListWave[coefIndex][1] = "LINK:"+CoefListWave[row][1]
3148                                                                        break;
3149                                                                case 2:
3150                                                                case 4:
3151                                                                        CoefListWave[coefIndex][col] = CoefListWave[row][col]
3152                                                                        break;
3153                                                                case 3:
3154                                                                        if (CoefSelWave[row][3] & 0x10)         // is it checked?
3155                                                                                CoefListWave[coefIndex][3] = " X"
3156                                                                        else
3157                                                                                CoefListWave[coefIndex][3] = ""
3158                                                                        endif
3159                                                                        break;
3160                                                        endswitch
3161                                                endif
3162                                        endif
3163                                        coefIndex += 1
3164                                endfor
3165                        endfor
3166                endif
3167        elseif ( (event == 1) && (row == -1) && (col >= 2) )
3168                selectionExists = (FindSelectedRows(CoefSelWave) > 0)
3169                string menuStr = "Select All;De-select All;"
3170                if (selectionExists)
3171                        menuStr += "Save Selection to Wave...;Load Selection From Wave...;"
3172                else
3173                        menuStr += "Save to Wave...;Load From Wave...;"
3174                endif
3175                if (col == 3)           // hold column
3176                        menuStr += "Clear all holds;"
3177                endif
3178                PopupContextualMenu menuStr
3179                if (V_flag > 0)
3180                        switch (V_flag)
3181                                case 1:
3182                                        CoefSelWave[][] = CoefSelWave[p][q] & ~9                // clear all selections
3183                                        CoefSelWave[][col] = CoefSelWave[p][col] | 1    // select all in this column
3184                                        break;
3185                                case 2:
3186                                        CoefSelWave[][] = CoefSelWave[p][q] & ~9
3187                                        break;
3188                                case 3:
3189                                        PopupContextualMenu "\\M1(  Save to Wave:;New Wave...;"+NewGF_ListInitGuessWaves(selectionExists, selectionExists)
3190
3191                                        if (V_flag > 0)
3192                                                if (CmpStr(S_selection, "New Wave...") == 0)
3193                                                        numRowsNeeded = selectionExists ? totalSelRealCoefsFromCoefList(1) : totalRealCoefsFromCoefList(0)
3194                                                        newName = NewGF_GetNewWaveName()
3195                                                        if (strlen(newName) == 0)
3196                                                                return 0
3197                                                        endif
3198                                                        Make/O/N=(numRowsNeeded)/D $newName
3199                                                        Wave w = $newName
3200                                                else
3201                                                        Wave w = $(S_selection)
3202                                                endif
3203                                               
3204                                                if (WaveExists(w))
3205                                                        SaveCoefListToWave(w, col, selectionExists, selectionExists)            // SaveOnlySelectedCells, OKToSaveLinkCells
3206                                                endif
3207                                        endif
3208                                        break;
3209                                case 4:
3210                                        selectionExists = (FindSelectedRows(CoefSelWave) > 0)
3211                                        PopupContextualMenu "\\M1(  Load From Wave:;"+NewGF_ListInitGuessWaves(selectionExists, selectionExists)
3212                                        if (V_flag > 0)
3213                                                Wave w = $(S_selection)
3214                                               
3215                                                if (WaveExists(w))
3216                                                        SetCoefListFromWave(w, col, selectionExists, selectionExists)
3217                                                endif
3218                                        endif
3219                                        break;
3220                                case 5:
3221                                        for (i = 0; i < DimSize(CoefSelWave, 0); i += 1)
3222                                                Make/O/N=(DimSize(CoefSelWave, 0)) GFTempHoldWave
3223                                                GFTempHoldWave = 0
3224                                                SetCoefListFromWave(GFTempHoldWave, 3, 0, 0)
3225                                                KillWaves/Z GFTempHoldWave
3226                                        endfor
3227                        endswitch
3228                endif
3229        endif
3230       
3231        return 0
3232end
3233
3234// finds the row number in the coefficient guess list (tab 1) corresponding to the cell in the tab0 coefficient list linked to by a linked cell
3235static Function NewGF_CoefRowForLink(linktext)
3236        String linktext
3237       
3238        Wave/T DataSetListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3239        Wave/T Tab0CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
3240
3241        Variable i,j
3242        Variable DSListRows = DimSize(DataSetListWave, 0)
3243        Variable coefIndex = 0;
3244       
3245        for (i = 0; i <         DSListRows; i += 1)
3246                Variable nc = str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
3247                for (j = 0; j < nc; j += 1)
3248                        if (CmpStr((Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]), linktext[5, strlen(linktext)-1]) == 0)
3249                                return coefIndex
3250                        endif
3251                        if (!IsLinkText(Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]))
3252                                coefIndex += 1
3253                        endif
3254                endfor
3255        endfor
3256end
3257
3258static Function NewGF_CoefListRowForLink(linktext)
3259        String linktext
3260       
3261        Wave/T DataSetListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3262        Wave/T Tab0CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
3263
3264        Variable i,j
3265        Variable DSListRows = DimSize(DataSetListWave, 0)
3266        Variable coefIndex = 0;
3267       
3268        for (i = 0; i <         DSListRows; i += 1)
3269                Variable nc = str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
3270                for (j = 0; j < nc; j += 1)
3271                        if (CmpStr((Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]), linktext[5, strlen(linktext)-1]) == 0)
3272                                return coefIndex
3273                        endif
3274                        coefIndex += 1
3275                endfor
3276        endfor
3277end
3278
3279
3280//******************************************************
3281// the function that runs when Fit! button is clicked
3282//******************************************************
3283
3284//static constant NewGF_DSList_YWaveCol = 0
3285//static constant NewGF_DSList_XWaveCol = 1
3286//static constant NewGF_DSList_FuncCol = 2
3287//static constant NewGF_DSList_NCoefCol = 3
3288
3289//static constant NewGF_DSList_FirstCoefCol = 0
3290
3291//static constant FuncPointerCol = 0
3292//static constant FirstPointCol = 1
3293//static constant LastPointCol = 2
3294//static constant NumFuncCoefsCol = 3
3295//static constant FirstCoefCol = 4
3296
3297static Function NewGF_DoTheFitButtonProc(ctrlName) : ButtonControl
3298        String ctrlName
3299
3300        Wave/T DataSetListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3301        Wave/T Tab0CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
3302        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
3303        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
3304       
3305        Variable numDataSets = DimSize(DataSetListWave, 0)
3306        Variable numCoefCols = DimSize(Tab0CoefListWave, 1)
3307        Variable i, j
3308        Variable nextFunc = 0
3309
3310        Variable curveFitOptions = 0
3311
3312        // build wave listing Fitting Function names. Have to check for repeats...
3313        Make/O/T/N=(numDataSets) root:Packages:NewGlobalFit:NewGF_FitFuncNames = ""
3314        Wave/T FitFuncNames = root:Packages:NewGlobalFit:NewGF_FitFuncNames
3315       
3316        for (i = 0; i < numDataSets; i += 1)
3317                if (!ItemListedInWave(DataSetListWave[i][NewGF_DSList_FuncCol][0], FitFuncNames))
3318                        FitFuncNames[nextFunc] = DataSetListWave[i][NewGF_DSList_FuncCol][0]
3319                        nextFunc += 1
3320                endif
3321        endfor
3322        Redimension/N=(nextFunc) FitFuncNames
3323       
3324        // build the linkage matrix required by DoNewGlobalFit
3325        // It is a coincidence that the matrix used by the list in the control panel has the same number of columns as the linkage matrix
3326        // so here we calculate the number of columns to protect against future changes
3327       
3328        Variable MaxNCoefs = numCoefCols - NewGF_DSList_FirstCoefCol
3329        Variable numLinkageCols = MaxNCoefs + FirstCoefCol
3330       
3331        Make/N=(numDataSets, numLinkageCols)/O root:Packages:NewGlobalFit:NewGF_LinkageMatrix
3332        Wave LinkageMatrix = root:Packages:NewGlobalFit:NewGF_LinkageMatrix
3333       
3334        Variable nRealCoefs = 0         // accumulates the number of independent coefficients (that is, non-link coefficients)
3335        for (i = 0; i < numDataSets; i += 1)
3336                Variable nc = str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
3337
3338                LinkageMatrix[i][FuncPointerCol] = ItemNumberInTextWaveList(DataSetListWave[i][NewGF_DSList_FuncCol][0], FitFuncNames)
3339                LinkageMatrix[i][FirstPointCol] = 0             // this is private info used by DoNewGlobalFit(). It will be filled in by DoNewGlobalFit()
3340                LinkageMatrix[i][LastPointCol] = 0              // this is private info used by DoNewGlobalFit(). It will be filled in by DoNewGlobalFit()
3341                LinkageMatrix[i][NumFuncCoefsCol] = nc
3342               
3343                for (j = NewGF_DSList_FirstCoefCol; j < numCoefCols; j += 1)
3344                        Variable linkMatrixCol = FirstCoefCol + j - NewGF_DSList_FirstCoefCol
3345                        if (j-NewGF_DSList_FirstCoefCol < nc)
3346                                String cellText = Tab0CoefListWave[i][j][0]
3347                                if (IsLinkText(cellText))
3348                                        LinkageMatrix[i][linkMatrixCol] = NewGF_CoefRowForLink(cellText)
3349                                else
3350                                        LinkageMatrix[i][linkMatrixCol] = nRealCoefs
3351                                        nRealCoefs += 1
3352                                endif
3353                        else
3354                                LinkageMatrix[i][linkMatrixCol] = -1
3355                        endif
3356                endfor
3357DoUpdate
3358        endfor
3359       
3360        // Build the data sets list wave
3361        Make/O/T/N=(numDataSets, 2) root:Packages:NewGlobalFit:NewGF_DataSetsList
3362        Wave/T DataSets = root:Packages:NewGlobalFit:NewGF_DataSetsList
3363        DataSets[][0,1] = DataSetListWave[p][q+NewGF_DSList_YWaveCol][1]                // layer 1 contains full paths
3364       
3365        // Add weighting, if necessary
3366        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_WeightingCheckBox
3367        if (V_value)
3368                GFUI_AddWeightWavesToDataSets(DataSets)
3369                NVAR/Z GlobalFit_WeightsAreSD = root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD
3370                if (NVAR_Exists(GlobalFit_WeightsAreSD) && GlobalFit_WeightsAreSD)
3371                        curveFitOptions += NewGFOptionWTISSTD
3372                endif
3373        endif
3374       
3375        // Add Mask, if necessary
3376        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_MaskingCheckBox
3377        if (V_value)
3378                GFUI_AddMaskWavesToDataSets(DataSets)
3379        endif
3380
3381        // Build the Coefficient wave and CoefNames wave
3382        Make/O/D/N=(nRealCoefs, 3) root:Packages:NewGlobalFit:NewGF_CoefWave
3383        Wave coefWave = root:Packages:NewGlobalFit:NewGF_CoefWave
3384        SetDimLabel 1,1,Hold,coefWave
3385        SetDimLabel 1,2,Epsilon,coefWave
3386        Make/O/T/N=(nRealCoefs) root:Packages:NewGlobalFit:NewGF_CoefficientNames
3387        Wave/T CoefNames = root:Packages:NewGlobalFit:NewGF_CoefficientNames
3388
3389        Variable coefIndex = 0
3390        Variable nTotalCoefs = DimSize(CoefListWave, 0)
3391        for (i = 0; i < nTotalCoefs; i += 1)
3392                if (!IsLinkText(CoefListWave[i][1]))
3393                        coefWave[coefIndex][0] = str2num(CoefListWave[i][2])
3394                        if (numtype(coefWave[coefIndex][0]) != 0)
3395                                TabControl NewGF_TabControl, win=NewGlobalFitPanel,value=1
3396                                NewGF_SetTabControlContent(1)
3397                                CoefSelWave = (CoefSelWave & ~1)
3398                                CoefSelWave[i][2] = 3
3399                                DoAlert 0, "There is a problem with the initial guess value in row "+num2str(i)+": it is not a number."
3400                                return -1
3401                        endif
3402                        coefWave[coefIndex][%Hold] = ((CoefSelWave[i][3] & 0x10) != 0)
3403                        coefWave[coefIndex][%Epsilon] = str2num(CoefListWave[i][4])
3404                        if (numtype(coefWave[coefIndex][%Epsilon]) != 0)
3405                                TabControl NewGF_TabControl, win=NewGlobalFitPanel,value=1
3406                                NewGF_SetTabControlContent(1)
3407                                CoefSelWave = (CoefSelWave & ~1)
3408                                CoefSelWave[i][4] = 3
3409                                DoAlert 0, "There is a problem with the Epsilon value in row "+num2str(i)+": it is not a number."
3410                                return -1
3411                        endif
3412                        CoefNames[coefIndex] = CoefListWave[i][1]
3413                        coefIndex += 1
3414                endif
3415        endfor
3416       
3417        // Build constraint wave, if necessary
3418        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_ConstraintsCheckBox
3419        if (V_value)
3420                NewGF_MakeConstraintWave()
3421                Wave/T/Z ConstraintWave = root:Packages:NewGlobalFit:GFUI_GlobalFitConstraintWave
3422        else
3423                Wave/T/Z ConstraintWave = $""
3424        endif
3425       
3426        // Set options
3427        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoCovarMatrix
3428        if (V_value)
3429                curveFitOptions += NewGFOptionCOV_MATRIX
3430        endif
3431
3432        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_CorrelationMatrixCheckBox
3433        if (V_value)
3434                curveFitOptions += NewGFOptionCOR_MATRIX
3435        endif
3436
3437        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_MakeFitCurvesCheck
3438        if (V_value)
3439                curveFitOptions += NewGFOptionMAKE_FIT_WAVES
3440        endif
3441
3442        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea AppendResultsCheck
3443        if (V_value)
3444                curveFitOptions += NewGFOptionAPPEND_RESULTS
3445        endif
3446       
3447        NVAR FitCurvePoints = root:Packages:NewGlobalFit:FitCurvePoints
3448       
3449        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoResidualCheck
3450        if (V_value)
3451                curveFitOptions += NewGFOptionCALC_RESIDS
3452        endif
3453       
3454        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoDestLogSpacingCheck
3455        if (V_value)
3456                curveFitOptions += NewGFOptionLOG_DEST_WAVE
3457        endif
3458       
3459        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_Quiet
3460        if (V_value)
3461                curveFitOptions += NewGFOptionQUIET
3462        endif
3463
3464        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_FitProgressGraphCheckBox
3465        if (V_value)
3466                curveFitOptions += NewGFOptionFIT_GRAPH
3467        endif
3468
3469        Variable err = DoNewGlobalFit(FitFuncNames, DataSets, LinkageMatrix, coefWave, CoefNames, ConstraintWave, curveFitOptions, FitCurvePoints, 1)
3470
3471        if (!err)
3472                SetCoefListFromWave(coefWave, 2, 0, 0)
3473        endif
3474end
3475
3476static Function/S MakeHoldString(CoefWave, quiet, justTheString)
3477        Wave CoefWave
3478        Variable quiet
3479        Variable justTheString
3480       
3481        String HS=""
3482
3483        Variable HoldCol = FindDimLabel(CoefWave, 1, "Hold")
3484        Variable nHolds = 0
3485        if (HoldCol > 0)
3486                if (!justTheString)
3487                        HS="/H=\""
3488                endif
3489                Variable nCoefs=DimSize(CoefWave, 0)
3490                Variable i
3491                for (i = 0; i < nCoefs; i += 1)
3492                        if (CoefWave[i][HoldCol])
3493                                HS += "1"
3494                                nHolds += 1
3495                        else
3496                                HS += "0"
3497                        endif
3498                endfor
3499                if (nHolds == 0)
3500                        return ""                       // ******** EXIT ***********
3501                endif
3502                // work from the end of the string removing extraneous zeroes
3503                if (strlen(HS) > 1)
3504                        for (i = strlen(HS)-1; i >= 0; i -= 1)
3505                                if (CmpStr(HS[i], "1") == 0)
3506                                        break
3507                                endif
3508                        endfor
3509                        if (i > 0)
3510                                HS = HS[0,i]
3511                        endif
3512                endif
3513                if (!justTheString)
3514                        HS += "\""
3515                endif
3516//              if (!quiet)
3517//                      print "Hold String=", HS
3518//              endif
3519                return HS                               // ******** EXIT ***********
3520        else
3521                return ""                               // ******** EXIT ***********
3522        endif
3523end
3524
3525//***********************************
3526//
3527// Constraints
3528//
3529//***********************************
3530
3531static Function ConstraintsCheckProc(ctrlName,checked) : CheckBoxControl
3532        String ctrlName
3533        Variable checked
3534       
3535        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3536        Variable NumSets = DimSize(ListWave, 0)
3537        Variable i
3538
3539        if (checked)
3540                if (NumSets == 0)
3541                        CheckBox NewGF_ConstraintsCheckBox, win=GlobalFitPanel, value=0
3542                        DoAlert 0, "You cannot add constraints until you have selected data sets"
3543                        return 0
3544                else
3545                        NVAR/Z NewGF_RebuildCoefListNow = root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow
3546                        if (!NVAR_Exists(NewGF_RebuildCoefListNow) || NewGF_RebuildCoefListNow)
3547                                NewGF_RebuildCoefListWave()
3548                        endif
3549                        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
3550                        Variable totalParams = 0
3551                        Variable CoefSize = DimSize(CoefListWave, 0)
3552                        for (i = 0; i < CoefSize; i += 1)
3553                                if (!IsLinkText(CoefListWave[i][1]))
3554                                        totalParams += 1
3555                                endif
3556                        endfor
3557
3558                        String saveDF = GetDatafolder(1)
3559                        SetDatafolder root:Packages:NewGlobalFit
3560                       
3561                        Wave/T/Z SimpleConstraintsListWave
3562                        if (!(WaveExists(SimpleConstraintsListWave) && (DimSize(SimpleConstraintsListWave, 0) == TotalParams)))
3563                                Make/O/N=(TotalParams, 5)/T SimpleConstraintsListWave=""
3564                        endif
3565                        Variable CoefIndex = 0
3566                        for (i = 0; i < CoefSize; i += 1)
3567                                if (!IsLinkText(CoefListWave[i][1]))
3568                                        SimpleConstraintsListWave[CoefIndex][0] = "K"+num2istr(CoefIndex)
3569                                        SimpleConstraintsListWave[CoefIndex][1] = CoefListWave[i][1]
3570                                        SimpleConstraintsListWave[CoefIndex][3] = "< K"+num2istr(CoefIndex)+" <"
3571                                        CoefIndex += 1
3572                                endif
3573                        endfor
3574                        Make/O/N=(TotalParams,5) SimpleConstraintsSelectionWave
3575                        SimpleConstraintsSelectionWave[][0] = 0         // K labels
3576                        SimpleConstraintsSelectionWave[][1] = 0         // coefficient labels
3577                        SimpleConstraintsSelectionWave[][2] = 2         // editable- greater than constraints
3578                        SimpleConstraintsSelectionWave[][3] = 0         // "< Kn <"
3579                        SimpleConstraintsSelectionWave[][4] = 2         // editable- less than constraints
3580                        SetDimLabel 1, 0, 'Kn', SimpleConstraintsListWave
3581                        SetDimLabel 1, 1, 'Actual Coefficient', SimpleConstraintsListWave
3582                        SetDimLabel 1, 2, 'Min', SimpleConstraintsListWave
3583                        SetDimLabel 1, 3, ' ', SimpleConstraintsListWave
3584                        SetDimLabel 1, 4, 'Max', SimpleConstraintsListWave
3585                       
3586                        Wave/Z/T MoreConstraintsListWave
3587                        if (!WaveExists(MoreConstraintsListWave))
3588                                Make/N=(1,1)/T/O  MoreConstraintsListWave=""
3589                                Make/N=(1,1)/O MoreConstraintsSelectionWave=6
3590                                SetDimLabel 1,0,'Enter Constraint Expressions', MoreConstraintsListWave
3591                        endif
3592                        MoreConstraintsSelectionWave=6
3593                       
3594                        SetDatafolder $saveDF
3595                       
3596                        if (WinType("NewGF_GlobalFitConstraintPanel") > 0)
3597                                DoWindow/F NewGF_GlobalFitConstraintPanel
3598                        else
3599                                fNewGF_GlobalFitConstraintPanel()
3600                        endif
3601                endif
3602        endif
3603End
3604
3605static Function fNewGF_GlobalFitConstraintPanel()
3606
3607        NewPanel /W=(45,203,451,568)
3608        DoWindow/C NewGF_GlobalFitConstraintPanel
3609        AutoPositionWindow/M=0/E/R=NewGlobalFitPanel NewGF_GlobalFitConstraintPanel
3610
3611        GroupBox SimpleConstraintsGroup,pos={5,7},size={394,184},title="Simple Constraints"
3612        Button SimpleConstraintsClearB,pos={21,24},size={138,20},proc=WM_NewGlobalFit1#SimpleConstraintsClearBProc,title="Clear List"
3613        ListBox constraintsList,pos={12,49},size={380,127},listwave=root:Packages:NewGlobalFit:SimpleConstraintsListWave
3614        ListBox constraintsList,selWave=root:Packages:NewGlobalFit:SimpleConstraintsSelectionWave, mode=7
3615        ListBox constraintsList,widths={30,189,50,40,50}, editStyle= 1,frame=2,userColumnResize=1
3616
3617        GroupBox AdditionalConstraintsGroup,pos={5,192},size={394,138},title="Additional Constraints"
3618        ListBox moreConstraintsList,pos={12,239},size={380,85}, listwave=root:Packages:NewGlobalFit:MoreConstraintsListWave
3619        ListBox moreConstraintsList,selWave=root:Packages:NewGlobalFit:MoreConstraintsSelectionWave, mode=4
3620        ListBox moreConstraintsList, editStyle= 1,frame=2,userColumnResize=1
3621        Button NewConstraintLineButton,pos={21,211},size={138,20},title="Add a Line", proc=WM_NewGlobalFit1#NewGF_NewCnstrntLineButtonProc
3622        Button RemoveConstraintLineButton01,pos={185,211},size={138,20},title="Remove Selection", proc=WM_NewGlobalFit1#RemoveConstraintLineButtonProc
3623
3624        Button GlobalFitConstraintsDoneB,pos={6,339},size={50,20},proc=WM_NewGlobalFit1#GlobalFitConstraintsDoneBProc,title="Done"
3625EndMacro
3626
3627static Function SimpleConstraintsClearBProc(ctrlName) : ButtonControl
3628        String ctrlName
3629
3630        Wave/Z/T SimpleConstraintsListWave = root:Packages:NewGlobalFit:SimpleConstraintsListWave
3631        SimpleConstraintsListWave[][2] = ""
3632        SimpleConstraintsListWave[][4] = ""
3633End
3634
3635static Function NewGF_NewCnstrntLineButtonProc(ctrlName) : ButtonControl
3636        String ctrlName
3637
3638        Wave/Z/T MoreConstraintsListWave = root:Packages:NewGlobalFit:MoreConstraintsListWave
3639        Wave/Z MoreConstraintsSelectionWave = root:Packages:NewGlobalFit:MoreConstraintsSelectionWave
3640        Variable nRows = DimSize(MoreConstraintsListWave, 0)
3641        InsertPoints nRows, 1, MoreConstraintsListWave, MoreConstraintsSelectionWave
3642        MoreConstraintsListWave[nRows] = ""
3643        MoreConstraintsSelectionWave[nRows] = 6
3644        Redimension/N=(nRows+1,1) MoreConstraintsListWave, MoreConstraintsSelectionWave
3645End
3646
3647static Function RemoveConstraintLineButtonProc(ctrlName) : ButtonControl
3648        String ctrlName
3649
3650        Wave/Z/T MoreConstraintsListWave = root:Packages:NewGlobalFit:MoreConstraintsListWave
3651        Wave/Z MoreConstraintsSelectionWave = root:Packages:NewGlobalFit:MoreConstraintsSelectionWave
3652        Variable nRows = DimSize(MoreConstraintsListWave, 0)
3653        Variable i = 0
3654        do
3655                if (MoreConstraintsSelectionWave[i] & 1)
3656                        if (nRows == 1)
3657                                MoreConstraintsListWave[0] = ""
3658                                MoreConstraintsSelectionWave[0] = 6
3659                        else
3660                                DeletePoints i, 1, MoreConstraintsListWave, MoreConstraintsSelectionWave
3661                                nRows -= 1
3662                        endif
3663                else
3664                        i += 1
3665                endif
3666        while (i < nRows)
3667        Redimension/N=(nRows,1) MoreConstraintsListWave, MoreConstraintsSelectionWave
3668End
3669
3670
3671static Function GlobalFitConstraintsDoneBProc(ctrlName) : ButtonControl
3672        String ctrlName
3673
3674        DoWindow/K NewGF_GlobalFitConstraintPanel
3675End
3676
3677static Function NewGF_MakeConstraintWave()
3678
3679        Wave/Z/T SimpleConstraintsListWave = root:Packages:NewGlobalFit:SimpleConstraintsListWave
3680        Wave/Z/T MoreConstraintsListWave = root:Packages:NewGlobalFit:MoreConstraintsListWave
3681       
3682        Make/O/T/N=0 root:Packages:NewGlobalFit:GFUI_GlobalFitConstraintWave
3683        Wave/T GlobalFitConstraintWave = root:Packages:NewGlobalFit:GFUI_GlobalFitConstraintWave
3684        Variable nextRow = 0
3685        String constraintExpression
3686        Variable i, nPnts=DimSize(SimpleConstraintsListWave, 0)
3687        for (i=0; i < nPnts; i += 1)
3688                if (strlen(SimpleConstraintsListWave[i][2]) > 0)
3689                        InsertPoints nextRow, 1, GlobalFitConstraintWave
3690                        sprintf constraintExpression, "K%d > %s", i, SimpleConstraintsListWave[i][2]
3691                        GlobalFitConstraintWave[nextRow] = constraintExpression
3692                        nextRow += 1
3693                endif
3694                if (strlen(SimpleConstraintsListWave[i][4]) > 0)
3695                        InsertPoints nextRow, 1, GlobalFitConstraintWave
3696                        sprintf constraintExpression, "K%d < %s", i, SimpleConstraintsListWave[i][4]
3697                        GlobalFitConstraintWave[nextRow] = constraintExpression
3698                        nextRow += 1
3699                endif
3700        endfor
3701       
3702        nPnts = DimSize(MoreConstraintsListWave, 0)
3703        for (i = 0; i < nPnts; i += 1)
3704                if (strlen(MoreConstraintsListWave[i]) > 0)
3705                        InsertPoints nextRow, 1, GlobalFitConstraintWave
3706                        GlobalFitConstraintWave[nextRow] = MoreConstraintsListWave[i]
3707                        nextRow += 1
3708                endif
3709        endfor
3710end
3711
3712//***********************************
3713//
3714// Weighting
3715//
3716//***********************************
3717
3718static Function NewGF_WeightingCheckProc(ctrlName,checked) : CheckBoxControl
3719        String ctrlName
3720        Variable checked
3721       
3722        if (checked)
3723                Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3724                Variable numSets = DimSize(ListWave, 0)
3725
3726                if (NumSets == 0)
3727                        CheckBox NewGF_WeightingCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea, value=0
3728                        DoAlert 0, "You cannot choose weighting waves until you have selected data sets."
3729                        return 0
3730                else
3731                        String saveDF = GetDatafolder(1)
3732                        SetDatafolder root:Packages:NewGlobalFit
3733                       
3734                        Wave/T/Z WeightingListWave
3735                        if (!(WaveExists(WeightingListWave) && (DimSize(WeightingListWave, 0) == NumSets)))
3736                                Make/O/N=(NumSets, 2)/T WeightingListWave=""
3737                        endif
3738                        WeightingListWave[][0] = ListWave[p][0][1]
3739                        Make/O/N=(NumSets, 2) WeightingSelectionWave
3740                        WeightingSelectionWave[][0] = 0         // Data Sets
3741                        WeightingSelectionWave[][1] = 0         // Weighting Waves; not editable- select from menu
3742                        SetDimLabel 1, 0, 'Data Set', WeightingListWave
3743                        SetDimLabel 1, 1, 'Weight Wave', WeightingListWave
3744                       
3745                        SetDatafolder $saveDF
3746                       
3747                        if (WinType("NewGF_WeightingPanel") > 0)
3748                                DoWindow/F NewGF_WeightingPanel
3749                        else
3750                                fNewGF_WeightingPanel()
3751                        endif
3752                       
3753//                      Variable/G root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD = NumVarOrDefault("root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD", 1)
3754                        Variable/G root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD = 1                //SRK force StdDev radio button
3755                        NVAR GlobalFit_WeightsAreSD = root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD
3756                        if (GlobalFit_WeightsAreSD)
3757                                WeightsSDRadioProc("WeightsSDRadio",1)
3758                        else
3759                                WeightsSDRadioProc("WeightsInvSDRadio",1)
3760                        endif
3761                                               
3762                endif
3763        endif   
3764end
3765
3766static Function fNewGF_WeightingPanel() : Panel
3767
3768        NewPanel /W=(339,193,745,408)
3769        DoWindow/C NewGF_WeightingPanel
3770        AutoPositionWindow/M=0/E/R=NewGlobalFitPanel NewGF_WeightingPanel
3771       
3772        ListBox WeightWaveListBox,pos={9,63},size={387,112}, mode=10, listWave = root:Packages:NewGlobalFit:WeightingListWave,userColumnResize=1
3773        ListBox WeightWaveListBox, selWave = root:Packages:NewGlobalFit:WeightingSelectionWave, frame=2,proc=WM_NewGlobalFit1#NewGF_WeightListProc
3774
3775        Button GlobalFitWeightDoneButton,pos={24,186},size={50,20},proc=WM_NewGlobalFit1#GlobalFitWeightDoneButtonProc,title="Done"
3776        Button GlobalFitWeightCancelButton,pos={331,186},size={50,20},proc=WM_NewGlobalFit1#GlobalFitWeightCancelButtonProc,title="Cancel"
3777
3778//SRK - disable - simply click on the row to set, based on name structure
3779        PopupMenu GlobalFitWeightWaveMenu,pos={9,5},size={152,20},title="Select Weight Wave"
3780        PopupMenu GlobalFitWeightWaveMenu,mode=0,value= #"WM_NewGlobalFit1#ListPossibleWeightWaves()", proc=WM_NewGlobalFit1#WeightWaveSelectionMenu
3781        PopupMenu GlobalFitWeightWaveMenu,disable=2
3782//eSRK
3783
3784//      Button WeightClearSelectionButton,pos={276,5},size={120,20},proc=WM_NewGlobalFit1#WeightClearSelectionButtonProc,title="Clear Selection"
3785//      Button WeightClearAllButton,pos={276,32},size={120,20},proc=WM_NewGlobalFit1#WeightClearSelectionButtonProc,title="Clear All"
3786
3787        GroupBox WeightStdDevRadioGroup,pos={174,4},size={95,54},title="Weights  are"
3788
3789        CheckBox WeightsSDRadio,pos={185,22},size={60,14},proc=WM_NewGlobalFit1#WeightsSDRadioProc,title="Std. Dev."
3790        CheckBox WeightsSDRadio,value= 1, mode=1
3791        CheckBox WeightsInvSDRadio,pos={185,38},size={73,14},proc=WM_NewGlobalFit1#WeightsSDRadioProc,title="1/Std. Dev."
3792        CheckBox WeightsInvSDRadio,value= 0, mode=1
3793EndMacro
3794
3795static Function NewGF_WeightListProc(ctrlName,row,col,event) : ListBoxControl
3796        String ctrlName     // name of this control
3797        Variable row        // row if click in interior, -1 if click in title
3798        Variable col        // column number
3799        Variable event      // event code
3800       
3801        if (event == 1)
3802                Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3803                Variable NumSets = DimSize(WeightingListWave, 0)
3804                if ( (row == -1) && (col == 1) )
3805                        Wave WeightingSelWave = root:Packages:NewGlobalFit:WeightingSelectionWave
3806                        WeightingSelWave[][1] = 1
3807                elseif ( (col == 1) && (row >= 0) && (row < NumSets) )
3808                        if (GetKeyState(0) == 0)
3809                                Wave/Z w = $(WeightingListWave[row][0])
3810                                if (WaveExists(w))
3811                                        //SRK - since I enforce the loading and naming, bypass the selection
3812                                        //String RowsText = num2str(DimSize(w, 0))
3813                                        //PopupContextualMenu "_calculated_;"+WaveList("*",";","MINROWS:"+RowsText+",MAXROWS:"+RowsText+",DIMS:1,CMPLX:0,TEXT:0,BYTE:0,WORD:0,INTEGER:0")
3814                                       
3815                                        //if (V_flag > 0)
3816                                        //      Wave/Z w = $S_selection
3817                                        //      if (WaveExists(w))
3818                                        //              WeightingListWave[row][1] = GetWavesDataFolder(w, 2)
3819                                        //      endif
3820                                        //endif
3821                                        String yStr = WeightingListWave[row][0]
3822                                        yStr = RemoveEnding(yStr , "i")
3823                                        WeightingListWave[row][1] = yStr + "s"
3824                                        //eSRK
3825                                endif
3826                        endif
3827                endif
3828        endif
3829end
3830
3831static Function GlobalFitWeightDoneButtonProc(ctrlName) : ButtonControl
3832        String ctrlName
3833
3834        Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3835        Variable NumSets = DimSize(WeightingListWave, 0)
3836       
3837        Variable i
3838        for (i = 0; i < NumSets; i += 1)
3839                Wave/Z w = $(WeightingListWave[i][1])
3840                if (!WaveExists(w))
3841                        ListBox WeightWaveListBox, win=NewGF_WeightingPanel, selRow = i
3842                        DoAlert 0, "The wave \""+WeightingListWave[i][1]+"\" does not exist."
3843                        WeightingListWave[i][1] = ""
3844                        return -1
3845                endif
3846        endfor
3847               
3848        DoWindow/K NewGF_WeightingPanel
3849End
3850
3851static Function GlobalFitWeightCancelButtonProc(ctrlName) : ButtonControl
3852        String ctrlName
3853
3854        DoWindow/K NewGF_WeightingPanel
3855        CheckBox NewGF_WeightingCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea, value=0
3856End
3857
3858static Function/S ListPossibleWeightWaves()
3859
3860        Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3861        Wave/Z WeightingSelectionWave=root:Packages:NewGlobalFit:WeightingSelectionWave
3862
3863        String DataSetName=""
3864        Variable i
3865       
3866        ControlInfo/W=NewGF_WeightingPanel WeightWaveListBox
3867        DataSetName = WeightingListWave[V_value][0]
3868       
3869        if (strlen(DataSetName) == 0)
3870                return "No Selection;"
3871        endif
3872       
3873        Wave/Z ds = $DataSetName
3874        if (!WaveExists(ds))
3875                return "Bad Data Set:"+DataSetName+";"
3876        endif
3877       
3878        Variable numpoints = DimSize(ds, 0)
3879        String theList = ""
3880        i=0
3881        do
3882                Wave/Z w = WaveRefIndexed("", i, 4)
3883                if (!WaveExists(w))
3884                        break
3885                endif
3886                if ( (DimSize(w, 0) == numpoints) && (WaveType(w) & 6) )                // select floating-point waves with the right number of points
3887                        theList += NameOfWave(w)+";"
3888                endif
3889                i += 1
3890        while (1)
3891       
3892        if (i == 0)
3893                return "None Available;"
3894        endif
3895       
3896        return theList
3897end
3898
3899static Function WeightWaveSelectionMenu(ctrlName,popNum,popStr) : PopupMenuControl
3900        String ctrlName
3901        Variable popNum
3902        String popStr
3903
3904        Wave/Z w = $popStr
3905        if (WaveExists(w))
3906                Wave/T WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3907                Wave WeightingSelWave = root:Packages:NewGlobalFit:WeightingSelectionWave
3908                Variable nrows = DimSize(WeightingListWave, 0)
3909                Variable i
3910                for (i = 0; i < nrows; i += 1)
3911                        if ( (WeightingSelWave[i][0] & 1) || (WeightingSelWave[i][1]) )
3912                                WeightingListWave[i][1] = GetWavesDatafolder(w, 2)
3913                        endif
3914                endfor
3915        endif
3916end
3917
3918//static Function WeightClearSelectionButtonProc(ctrlName) : ButtonControl
3919//      String ctrlName
3920//
3921//      Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3922//      StrSwitch (ctrlName)
3923//              case "WeightClearSelectionButton":
3924//                      Wave WeightingSelWave = root:Packages:NewGlobalFit:WeightingSelectionWave
3925//                      Variable nrows = DimSize(WeightingListWave, 0)
3926//                      Variable i
3927//                      for (i = 0; i < nrows; i += 1)
3928//                              if ( (WeightingSelWave[i][0] & 1) || (WeightingSelWave[i][1]) )
3929//                                      WeightingListWave[i][1] = ""
3930//                              endif
3931//                      endfor
3932//                      break;
3933//              case "WeightClearAllButton":
3934//                      WeightingListWave[][1] = ""
3935//                      break;
3936//      endswitch
3937//End
3938
3939static Function WeightsSDRadioProc(name,value)
3940        String name
3941        Variable value
3942       
3943        NVAR GlobalFit_WeightsAreSD= root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD
3944       
3945        strswitch (name)
3946                case "WeightsSDRadio":
3947                        GlobalFit_WeightsAreSD = 1
3948                        break
3949                case "WeightsInvSDRadio":
3950                        GlobalFit_WeightsAreSD = 0
3951                        break
3952        endswitch
3953        CheckBox WeightsSDRadio, win=NewGF_WeightingPanel, value= GlobalFit_WeightsAreSD==1
3954        CheckBox WeightsInvSDRadio, win=NewGF_WeightingPanel, value= GlobalFit_WeightsAreSD==0
3955End
3956
3957// This function is strictly for the use of the Global Analysis control panel. It assumes that the DataSets
3958// wave so far has just two columns, the Y and X wave columns
3959static Function GFUI_AddWeightWavesToDataSets(DataSets)
3960        Wave/T DataSets
3961       
3962        Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3963       
3964        Redimension/N=(-1, 3) DataSets
3965        SetDimLabel 1, 2, Weights, DataSets
3966       
3967        Variable numSets = DimSize(DataSets, 0)
3968        Variable i
3969        for (i = 0; i < NumSets; i += 1)
3970                Wave/Z w = $(WeightingListWave[i][1])
3971                if (WaveExists(w))
3972                        wave/Z yw = $(DataSets[i][0])
3973                        if (WaveExists(yw) && (numpnts(w) != numpnts(yw)))
3974                                DoAlert 0,"The weighting wave \""+WeightingListWave[i][1]+"\" has a different number points than Y wave \""+(DataSets[i][0])+"\""
3975                                return -1
3976                        endif
3977                        DataSets[i][2] = WeightingListWave[i][1]
3978                else
3979                        Redimension/N=(-1,2) DataSets
3980                        DoAlert 0,"The weighting wave \""+WeightingListWave[i][1]+"\" for Y wave \""+(DataSets[i][0])+"\" does not exist."
3981                        return -1
3982                endif
3983        endfor
3984       
3985        return 0
3986end
3987
3988static Function GFUI_AddMaskWavesToDataSets(DataSets)
3989        Wave/T DataSets
3990       
3991        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
3992       
3993        Variable startingNCols = DimSize(DataSets, 1)
3994        Redimension/N=(-1, startingNCols+1) DataSets
3995        SetDimLabel 1, startingNCols, Masks, DataSets
3996       
3997        Variable numSets = DimSize(DataSets, 0)
3998        Variable i
3999        for (i = 0; i < NumSets; i += 1)
4000                Wave/Z w = $(MaskingListWave[i][1])
4001                if (WaveExists(w))
4002                        wave/Z yw = $(DataSets[i][0])
4003                        if (WaveExists(yw) && (numpnts(w) != numpnts(yw)))
4004                                DoAlert 0,"The mask wave \""+MaskingListWave[i][1]+"\" has a different number points than Y wave \""+(DataSets[i][0])+"\""
4005                                return -1
4006                        endif
4007                        DataSets[i][startingNCols] = MaskingListWave[i][1]
4008                else
4009                        Redimension/N=(-1,startingNCols) DataSets
4010                        DoAlert 0,"The mask wave \""+MaskingListWave[i][1]+"\" for Y wave \""+(DataSets[i][0])+"\" does not exist."
4011                        return -1
4012                endif
4013        endfor
4014       
4015        return 0
4016end
4017
4018
4019static Function NewGF_CovMatrixCheckProc(ctrlName,checked) : CheckBoxControl
4020        String ctrlName
4021        Variable checked
4022
4023        if (!checked)
4024                Checkbox NewGF_CorrelationMatrixCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=0
4025        endif
4026End
4027
4028static Function NewGF_CorMatrixCheckProc(ctrlName,checked) : CheckBoxControl
4029        String ctrlName
4030        Variable checked
4031
4032        if (checked)
4033                Checkbox NewGF_DoCovarMatrix, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=1
4034        endif
4035End
4036
4037
4038static Function NewGF_FitCurvesCheckProc(ctrlName,checked) : CheckBoxControl
4039        String ctrlName
4040        Variable checked
4041
4042        if (!checked)
4043                Checkbox NewGF_AppendResultsCheckbox, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=0
4044                Checkbox NewGF_DoResidualCheck, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=0
4045        endif
4046End
4047
4048static Function NewGF_AppendResultsCheckProc(ctrlName,checked) : CheckBoxControl
4049        String ctrlName
4050        Variable checked
4051
4052        if (checked)
4053                Checkbox NewGF_MakeFitCurvesCheck, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=1
4054        endif
4055End
4056
4057static Function NewGF_CalcResidualsCheckProc(ctrlName,checked) : CheckBoxControl
4058        String ctrlName
4059        Variable checked
4060
4061        if (checked)
4062                Checkbox NewGF_MakeFitCurvesCheck, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=1
4063        endif
4064End
4065
4066
4067//***********************************
4068//
4069// Data masking
4070//
4071//***********************************
4072
4073static Function NewGF_MaskingCheckProc(ctrlName,checked) : CheckBoxControl
4074        String ctrlName
4075        Variable checked
4076       
4077        if (checked)
4078                Wave/T DataSetList = root:Packages:NewGlobalFit:NewGF_DataSetListWave
4079                Variable numSets = DimSize(DataSetList, 0)
4080
4081                if (NumSets == 0)
4082                        CheckBox NewGF_MaskingCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea, value=0
4083                        DoAlert 0, "You cannot add Masking waves until you have selected data sets."
4084                        return 0
4085                else
4086                        String saveDF = GetDatafolder(1)
4087                        SetDatafolder root:Packages:NewGlobalFit
4088                       
4089                        Wave/T/Z MaskingListWave
4090                        if (!(WaveExists(MaskingListWave) && (DimSize(MaskingListWave, 0) == NumSets)))
4091                                Make/O/N=(NumSets, 2)/T MaskingListWave=""
4092                        endif
4093                        MaskingListWave[][0] = DataSetList[p][0][1]
4094                        Make/O/N=(NumSets, 2) MaskingSelectionWave
4095                        MaskingSelectionWave[][0] = 0           // Data Sets
4096                        MaskingSelectionWave[][1] = 0           // Masking Waves; not editable- select from menu
4097                        SetDimLabel 1, 0, 'Data Set', MaskingListWave
4098                        SetDimLabel 1, 1, 'Mask Wave', MaskingListWave
4099                       
4100                        SetDatafolder $saveDF
4101                       
4102                        if (WinType("NewGF_GlobalFitMaskingPanel") > 0)
4103                                DoWindow/F NewGF_GlobalFitMaskingPanel
4104                        else
4105                                fNewGF_GlobalFitMaskingPanel()
4106                        endif
4107                endif
4108        //SRK - hide unused cursors
4109        else
4110                //not checked, remove cursors
4111                Cursor/K A
4112                Cursor/K B
4113                HideInfo
4114        //eSRK
4115        endif   
4116end
4117
4118static Function fNewGF_GlobalFitMaskingPanel() : Panel
4119
4120        NewPanel /W=(339,193,745,408)
4121        DoWindow/C NewGF_GlobalFitMaskingPanel
4122        AutoPositionWindow/M=0/E/R=NewGlobalFitPanel NewGF_GlobalFitMaskingPanel
4123       
4124        ListBox MaskWaveListBox,pos={9,63},size={387,112}, mode=10, listWave = root:Packages:NewGlobalFit:MaskingListWave,userColumnResize=1
4125        //SRK - use my own selection procedure, not the contextual menu in the ListBox
4126//      ListBox MaskWaveListBox, selWave = root:Packages:NewGlobalFit:MaskingSelectionWave, frame=2, proc=WM_NewGlobalFit1#NewGF_MaskListProc
4127        ListBox MaskWaveListBox, selWave = root:Packages:NewGlobalFit:MaskingSelectionWave, frame=2
4128        //eSRK
4129        Button GlobalFitMaskDoneButton,pos={24,186},size={50,20},proc=WM_NewGlobalFit1#GlobalFitMaskDoneButtonProc,title="Done"
4130        Button GlobalFitMaskCancelButton,pos={331,186},size={50,20},proc=WM_NewGlobalFit1#GlobalFitMaskCancelButtonProc,title="Cancel"
4131        PopupMenu GlobalFitMaskWaveMenu,pos={9,5},size={152,20},title="Select Mask Wave"
4132        PopupMenu GlobalFitMaskWaveMenu,mode=0,value= #"WM_NewGlobalFit1#ListPossibleMaskWaves()", proc=WM_NewGlobalFit1#MaskWaveSelectionMenu
4133        Button MaskClearSelectionButton,pos={276,5},size={120,20},proc=WM_NewGlobalFit1#MaskClearSelectionButtonProc,title="Clear Selection"
4134        Button MaskClearAllButton,pos={276,32},size={120,20},proc=WM_NewGlobalFit1#MaskClearSelectionButtonProc,title="Clear All"
4135       
4136        //SRK
4137        Button MaskFromCursorsButton,pos={130,32},size={135,20},proc=MaskFromCursorsButtonProc,title="Mask From Cursors"
4138        ListBox MaskWaveListBox,proc=MaskListBoxSelectionProc
4139        Button MaskShowInfoButton,pos={9,32},size={110,20},proc=MaskShowInfoButtonProc,title="Show Cursors"
4140        //eSRK
4141EndMacro
4142
4143//SRK
4144// make a temporary masking wave from the selected data set
4145// and the cursor positions
4146//
4147Function MaskFromCursorsButtonProc(ctrlName) : ButtonControl
4148        String ctrlName
4149
4150        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4151        Wave selWave = root:Packages:NewGlobalFit:MaskingSelectionWave
4152       
4153        Variable numRow=DimSize(selWave, 0),ii=0
4154        String DataSetName=""
4155        do
4156                if(selWave[ii][0] || selWave[ii][1])
4157                        break
4158                endif
4159                ii+=1
4160        while(ii<numRow)
4161        numRow=ii
4162       
4163        DataSetName = MaskingListWave[numRow][0]                //"root:yTraceName"
4164        Wave w = $DataSetName
4165       
4166        Duplicate/O $DataSetName,$(DataSetName+"mask")  //mask is in root: folder
4167       
4168        MaskingListWave[numRow][1] = DataSetName+"mask"
4169       
4170        Wave mm = $(DataSetName+"mask")
4171        mm=1            //mask nothing as the default
4172       
4173        //set the masking based on the cursors
4174        Make/O/N=2 csrPts
4175        csrPts[0] = xcsr(A)
4176        csrPts[1] = xcsr(B)
4177        Sort csrPts,csrPts              //pt[0] is smaller - guaranteed
4178       
4179        if(csrPts[0] > 0)
4180                mm[0,csrPts[0]-1] = 0
4181        endif
4182        if(csrPts[1] < (numpnts(mm)-1) )
4183                mm[csrPts[1]+1,numpnts(mm)-1] = 0
4184        endif
4185       
4186        Killwaves/Z csrPts     
4187End
4188
4189//SRK
4190Function MaskShowInfoButtonProc(ctrlName) : ButtonControl
4191        String ctrlName
4192        ShowInfo                //topmost graph
4193        return(0)
4194End
4195
4196//SRK
4197// based on the selected data set in the list box, put cursors
4198// on the proper data set, and put them at the right points
4199// if the masking wave exists
4200//
4201Function MaskListBoxSelectionProc(ctrlName,row,col,event)       // : ListboxControl
4202        String ctrlName     // name of this control
4203        Variable row        // row if click in interior, -1 if click in title
4204        Variable col        // column number
4205        Variable event      // event code
4206       
4207        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4208       
4209        String str=MaskingListWave[row][0]              //"root:yTraceName"
4210        Variable ptA=0,ptB=numpnts($(str[5,strlen(str)-1]))-1           //default to end points
4211        WAVE/Z mm = $(str+"mask")
4212        if(waveexists(mm))
4213                FindLevel/P/Q mm,1
4214                ptA = V_LevelX
4215                FindLevel/P/Q/R=[ptA] mm,0
4216                if(V_flag==0)
4217                        ptB = V_LevelX-1                //level was found, use it. otherwise use default
4218                endif
4219        endif
4220        // get the right target window, hopefully the top graph
4221        String tmp= StringFromList(0,WinList("*", ";","WIN:1"),";")             //first graph is "topmost"
4222        Cursor/P/W=$tmp A, $(ParseFilePath(0, str, ":", 1, 0)),ptA                      //just give me the wave name, not the full path
4223        Cursor/P/W=$tmp B, $(ParseFilePath(0, str, ":", 1, 0)),ptB
4224       
4225        return 0            // other return values reserved
4226End
4227
4228static Function NewGF_MaskListProc(ctrlName,row,col,event) : ListBoxControl
4229        String ctrlName     // name of this control
4230        Variable row        // row if click in interior, -1 if click in title
4231        Variable col        // column number
4232        Variable event      // event code
4233       
4234        if (event == 1)
4235                Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4236                Variable numSets = DimSize(MaskingListWave, 0)
4237                if ( (row == -1) && (col == 1) )
4238                        Wave MaskingSelWave = root:Packages:NewGlobalFit:MaskingSelectionWave
4239                        MaskingSelWave[][1] = 1
4240                elseif ( (col == 1) && (row >= 0) && (row < NumSets) )
4241                        if (GetKeyState(0) == 0)
4242                                Wave/Z w = $(MaskingListWave[row][0])
4243                                if (WaveExists(w))
4244                                        String RowsText = num2str(DimSize(w, 0))
4245                                        PopupContextualMenu "_calculated_;"+WaveList("*",";","MINROWS:"+RowsText+",MAXROWS:"+RowsText+",DIMS:1,CMPLX:0,TEXT:0,BYTE:0,WORD:0,INTEGER:0")
4246                                        if (V_flag > 0)
4247                                                Wave/Z w = $S_selection
4248                                                if (WaveExists(w))
4249                                                        MaskingListWave[row][1] = GetWavesDataFolder(w, 2)
4250                                                endif
4251                                        endif
4252                                endif
4253                        endif
4254                endif
4255        endif
4256end
4257
4258static Function GlobalFitMaskDoneButtonProc(ctrlName) : ButtonControl
4259        String ctrlName
4260
4261        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4262        Variable numSets = DimSize(MaskingListWave, 0)
4263
4264        Variable i
4265        for (i = 0; i < NumSets; i += 1)
4266                Wave/Z w = $(MaskingListWave[i][1])
4267                if (!WaveExists(w))
4268                        if (strlen(MaskingListWave[i][1]) != 0)
4269                                ListBox MaskWaveListBox, win=NewGF_GlobalFitMaskingPanel, selRow = i
4270                                DoAlert 0, "The wave \""+MaskingListWave[i][1]+"\" does not exist."
4271                                MaskingListWave[i][1] = ""
4272                                return -1
4273                        endif
4274                endif
4275        endfor
4276               
4277        DoWindow/K NewGF_GlobalFitMaskingPanel
4278End
4279
4280static Function GlobalFitMaskCancelButtonProc(ctrlName) : ButtonControl
4281        String ctrlName
4282
4283        DoWindow/K NewGF_GlobalFitMaskingPanel
4284        CheckBox NewGF_MaskingCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea, value=0
4285End
4286
4287static Function/S ListPossibleMaskWaves()
4288
4289        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4290        Wave/Z MaskingSelectionWave=root:Packages:NewGlobalFit:MaskingSelectionWave
4291        Variable NumSets= DimSize(MaskingListWave, 0)
4292
4293        String DataSetName=""
4294        Variable i
4295       
4296        ControlInfo/W=NewGF_GlobalFitMaskingPanel MaskWaveListBox
4297        DataSetName = MaskingListWave[V_value][0]
4298       
4299        if (strlen(DataSetName) == 0)
4300                return "No Selection;"
4301        endif
4302       
4303        Wave/Z ds = $DataSetName
4304        if (!WaveExists(ds))
4305                return "Unknown Data Set;"
4306        endif
4307       
4308        Variable numpoints = DimSize(ds, 0)
4309        String theList = ""
4310        i=0
4311        do
4312                Wave/Z w = WaveRefIndexed("", i, 4)
4313                if (!WaveExists(w))
4314                        break
4315                endif
4316                if ( (DimSize(w, 0) == numpoints) && (WaveType(w) & 6) )                // select floating-point waves with the right number of points
4317                        theList += NameOfWave(w)+";"
4318                endif
4319                i += 1
4320        while (1)
4321       
4322        if (i == 0)
4323                return "None Available;"
4324        endif
4325       
4326        return theList
4327end
4328
4329static Function MaskWaveSelectionMenu(ctrlName,popNum,popStr) : PopupMenuControl
4330        String ctrlName
4331        Variable popNum
4332        String popStr
4333
4334        Wave/Z w = $popStr
4335        if (WaveExists(w))
4336                Wave/T MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4337                Wave MaskingSelWave = root:Packages:NewGlobalFit:MaskingSelectionWave
4338                Variable nrows = DimSize(MaskingListWave, 0)
4339                Variable i
4340                for (i = 0; i < nrows; i += 1)
4341                        if ( (MaskingSelWave[i][0] & 1) || (MaskingSelWave[i][1]) )
4342                                MaskingListWave[i][1] = GetWavesDatafolder(w, 2)
4343                        endif
4344                endfor
4345        endif
4346end
4347
4348static Function MaskClearSelectionButtonProc(ctrlName) : ButtonControl
4349        String ctrlName
4350
4351        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4352        StrSwitch (ctrlName)
4353                case "MaskClearSelectionButton":
4354                        Wave MaskingSelWave = root:Packages:NewGlobalFit:MaskingSelectionWave
4355                        Variable nrows = DimSize(MaskingListWave, 0)
4356                        Variable i
4357                        for (i = 0; i < nrows; i += 1)
4358                                if ( (MaskingSelWave[i][0] & 1) || (MaskingSelWave[i][1]) )
4359                                        MaskingListWave[i][1] = ""
4360                                endif
4361                        endfor
4362                        break;
4363                case "MaskClearAllButton":
4364                        MaskingListWave[][1] = ""
4365                        break;
4366        endswitch
4367End
4368
4369
4370
4371//***********************************
4372//
4373// Load/Save initial guesses from/to a wave
4374//
4375//***********************************
4376
4377Function/S NewGF_ListInitGuessWaves(SelectedOnly, LinkRowsOK)
4378        Variable SelectedOnly
4379        Variable LinkRowsOK
4380
4381        Variable numrows
4382//      ControlInfo/W=NewGlobalFitPanel#Tab1ContentPanel NewGF_InitGuessCopySelCheck
4383        if (SelectedOnly)
4384                numrows = totalSelRealCoefsFromCoefList(LinkRowsOK)
4385        else
4386                numrows = totalRealCoefsFromCoefList(LinkRowsOK)
4387        endif
4388       
4389        String numrowsstr = num2str(numrows)
4390        return WaveList("*", ";", "DIMS:1,MINROWS:"+numrowsstr+",MAXROWS:"+numrowsstr+",BYTE:0,INTEGER:0,WORD:0,CMPLX:0,TEXT:0")
4391end
4392
4393char ctrlName[MAX_OBJ_NAME+1]   Control name.
4394char win[MAX_WIN_PATH+1]        Host (sub)window.
4395STRUCT Rect winRect     Local coordinates of host window.
4396STRUCT Rect ctrlRect    Enclosing rectangle of the control.
4397STRUCT Point mouseLoc   Mouse location.
4398Int32 eventCode Event that caused the procedure to execute. Main event is mouse up=2.
4399String userdata Primary (unnamed) user data. If this changes, it is written back automatically.
4400Int32 popNum    Item number currently selected (1-based).
4401char popStr[MAXCMDLEN]  Contents of current popup item.
4402
4403Function NewGF_SetCoefsFromWaveProc(PU_Struct) : PopupMenuControl
4404        STRUCT WMPopupAction &PU_Struct
4405
4406        if (PU_Struct.eventCode == 2)                   // mouse up
4407                Wave w = $(PU_Struct.popStr)
4408                if (!WaveExists(w))
4409                        DoAlert 0, "The wave you selected does not exist for some reason."
4410                        return 0
4411                endif
4412               
4413                SetCoefListFromWave(w, 2, 0, 0)
4414        endif
4415end
4416
4417Function NewGF_SaveCoefsToWaveProc(PU_Struct) : PopupMenuControl
4418        STRUCT WMPopupAction &PU_Struct
4419
4420        if (PU_Struct.eventCode == 2)                   // mouse up
4421                if (CmpStr(PU_Struct.popStr, "New Wave...") == 0)
4422                        Variable numRowsNeeded = totalRealCoefsFromCoefList(0)
4423                        String newName = NewGF_GetNewWaveName()
4424                        if (strlen(newName) == 0)
4425                                return 0
4426                        endif
4427                        Make/O/N=(numRowsNeeded)/D $newName
4428                        Wave w = $newName
4429                else
4430                        Wave w = $(PU_Struct.popStr)
4431                endif
4432               
4433                SaveCoefListToWave(w, 2, 0, 0)
4434        endif
4435end
4436
4437Function/S NewGF_GetNewWaveName()
4438
4439        String newName
4440        Prompt newName, "Enter a name for the new wave:"
4441        DoPrompt "Get New Wave Name", newName
4442        if (V_flag)
4443                return ""
4444        endif
4445       
4446        return newName
4447end
4448       
4449//***********************************
4450//
4451// Utility functions
4452//
4453//***********************************
4454
4455// returns semicolon-separated list of items in a selected column of a 1D or 2D text wave
4456static Function/S TextWaveToList(twave, column)
4457        Wave/T twave
4458        Variable column
4459       
4460        String returnValue = ""
4461        Variable nRows = DimSize(twave, 0)
4462        Variable i
4463       
4464        for (i = 0; i < nRows; i += 1)
4465                returnValue += (twave[i][column])+";"
4466        endfor
4467       
4468        return returnValue
4469end
4470
4471static Function IsLinkText(theText)
4472        String theText
4473       
4474        return (CmpStr(theText[0,4], "LINK:") == 0)
4475end
4476
4477static Function ItemListedInWave(Item, theWave)
4478        String Item
4479        Wave/T theWave
4480       
4481        return ItemNumberInTextWaveList(Item, theWave) >= 0
4482end
4483
4484static Function ItemNumberInTextWaveList(Item, theWave)
4485        String Item
4486        Wave/T theWave
4487       
4488        Variable i
4489        Variable npnts = DimSize(theWave, 0)
4490        Variable itemNumber = -1
4491       
4492        for (i = 0; i < npnts; i += 1)
4493                if ( (strlen(theWave[i]) > 0) && (CmpStr(theWave[i], Item) == 0) )
4494                        itemNumber = i
4495                        break
4496                endif
4497        endfor
4498       
4499        return itemNumber
4500end
4501
4502// makes a 1D or 2D text wave with each item from a semicolon-separated list in the wave's rows
4503// in the selected column. You are free to fill other columns as you wish.
4504static Function ListToTwave(theList, twaveName, columns, column)
4505        String theList
4506        String twaveName
4507        Variable columns
4508        Variable column
4509       
4510        Variable nRows = ItemsInList(theList)
4511        Variable i
4512       
4513        Make/T/O/N=(nRows, columns) $twaveName
4514        Wave/T twave = $twaveName
4515       
4516        for (i = 0; i < nRows; i += 1)
4517                twave[i][column] = StringFromList(i, theList)
4518        endfor
4519end
4520
4521static Function totalCoefsFromCoefList()
4522
4523        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4524       
4525        return DimSize(CoefListWave, 0)
4526end
4527
4528static Function totalRealCoefsFromCoefList(LinkRowsOK)
4529        Variable LinkRowsOK
4530
4531        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4532
4533        Variable i
4534        Variable totalNonlinkRows = 0
4535        Variable numrows = DimSize(CoefListWave, 0)
4536        for (i = 0; i < numrows; i += 1)
4537                if (LinkRowsOK || !IsLinkText(CoefListWave[i][1]))
4538                        totalNonlinkRows += 1
4539                endif
4540        endfor
4541       
4542        return totalNonlinkRows
4543end
4544
4545static Function totalSelRealCoefsFromCoefList(LinkRowsOK)
4546        Variable LinkRowsOK
4547
4548        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4549        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
4550
4551        Variable i
4552        Variable totalNonlinkRows = 0
4553        Variable numrows = DimSize(CoefListWave, 0)
4554        for (i = 0; i < numrows; i += 1)
4555                if (LinkRowsOK || !IsLinkText(CoefListWave[i][1]))
4556                        if (IsRowSelected(CoefSelWave, i))
4557                                totalNonlinkRows += 1
4558                        endif
4559                endif
4560        endfor
4561       
4562        return totalNonlinkRows
4563end
4564
4565static Function SetCoefListFromWave(w, col, SetOnlySelectedCells, OKtoSetLinkRows)
4566        Wave w
4567        Variable col
4568        Variable SetOnlySelectedCells
4569        Variable OKtoSetLinkRows
4570       
4571        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4572        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
4573
4574        Variable coefIndex = 0;
4575        Variable i,j
4576        Variable nTotalCoefs = DimSize(CoefListWave, 0)
4577       
4578        String formatStr = "%.15g"
4579        if ( (WaveType(w) & 4) == 0)            // it's not a double-precision wave
4580                formatStr = "%.6g"
4581        endif
4582       
4583        for (i = 0; i < nTotalCoefs; i += 1)            // indent 1
4584//              if ( SetOnlySelectedCells && ((CoefSelWave[i][col] & 9) == 0) )
4585                if ( SetOnlySelectedCells && !IsRowSelected(CoefSelWave, i) )
4586                        continue
4587                endif
4588//              if (!OKtoSetLinkRows && !IsLinkText(CoefListWave[i][1]))
4589                if (!IsLinkText(CoefListWave[i][1]))            // indent 2
4590                        // first part sets the coefficient list wave text from the appropriate element in the input wave
4591               
4592                        if (col == 3)
4593                                if (w[coefIndex][0])
4594                                        CoefSelWave[i][col] = 0x20 + 0x10
4595                                else
4596                                        CoefSelWave[i][col] = 0x20
4597                                endif
4598                        else
4599                                string dumstr
4600                                sprintf dumstr, formatStr, w[coefIndex][0]
4601                                Variable nstr = strlen(dumstr)
4602                                for (j = 0; j < nstr; j += 1)
4603                                        if (char2num(dumstr[j]) != char2num(" "))
4604                                                break
4605                                        endif
4606                                endfor
4607                                if (j > 0)
4608                                        dumstr = dumstr[j, strlen(dumstr)-1]
4609                                endif
4610                                CoefListWave[i][col] = dumstr
4611                        endif
4612                else            // indent 2
4613                        string linktext
4614                        // We've hit a link cell (refers to an earlier row)
4615                        //
4616                        // If we are setting the entire wave, rather than setting the value in the row, we should instead copy the value
4617                        // from the row containing the master copy (the row to which the link refers). (first IF block)
4618                        //
4619                        // If we are setting selected rows, and one of them is a link to another row, we should set the value of the master row
4620                        // and any other rows that link to it.
4621                        if (!SetOnlySelectedCells)              // indent 3
4622                                // copy linked text from master row when we encounter a linked cell. The links should always be after the cell they link to.
4623                                linktext = (CoefListWave[i][1])[5,strlen(CoefListWave[i][1])-1]
4624                                for (j = 0; j < nTotalCoefs; j += 1)
4625                                        if (CmpStr(linktext, CoefListWave[j][1]) == 0)
4626                                                if (col == 3)
4627                                                        if (CoefSelWave[j][col] & 0x10)
4628                                                                CoefListWave[i][col] = " X"
4629                                                        else
4630                                                                CoefListWave[i][col] = ""
4631                                                        endif
4632                                                else
4633                                                        CoefListWave[i][col] = CoefListWave[j][col]
4634                                                endif
4635                                                break
4636                                        endif
4637                                endfor
4638                                continue                // skip incrementing coefIndex
4639                        elseif (OKtoSetLinkRows)                // indent 3
4640                                linktext = (CoefListWave[i][1])[5,strlen(CoefListWave[i][1])-1]
4641                                for (j = 0; j < nTotalCoefs; j += 1)            // indent 4
4642                                        if ( (CmpStr(linktext, CoefListWave[j][1]) == 0) || (CmpStr(CoefListWave[i][1], CoefListWave[j][1]) == 0) )             // indent 5
4643                                                // we have found the master row                                         or one of the linked rows
4644                                                if (col == 3)           // indent 6
4645                                                        if (w[coefIndex][0])
4646                                                                CoefSelWave[j][col] = 0x20 + 0x10
4647                                                        else
4648                                                                CoefSelWave[j][col] = 0x20
4649                                                        endif
4650                                                else            // indent 6
4651                                                        sprintf dumstr, formatStr, w[coefIndex][0]
4652                                                        nstr = strlen(dumstr)
4653                                                        Variable k
4654                                                        for (k = 0; k < nstr; k += 1)
4655                                                                if (char2num(dumstr[k]) != char2num(" "))
4656                                                                        break
4657                                                                endif
4658                                                        endfor
4659                                                        if (k > 0)
4660                                                                dumstr = dumstr[k, strlen(dumstr)-1]
4661                                                        endif
4662                                                        CoefListWave[j][col] = dumstr
4663                                                endif           // indent 6
4664//                                              coefIndex += 1
4665                                        endif           // indent 5
4666                                endfor          // indent 4
4667                        endif           // indent 3
4668                endif           // indent 2
4669                coefIndex += 1
4670        endfor          // indent 1
4671end
4672
4673static Function SaveCoefListToWave(w, col, SaveOnlySelectedCells, OKToSaveLinkCells)
4674        Wave w
4675        Variable col
4676        Variable SaveOnlySelectedCells
4677        Variable OKToSaveLinkCells
4678       
4679        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4680        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
4681        Variable ntotalCoefs = totalCoefsFromCoefList()
4682        Variable i
4683        Variable waveIndex = 0
4684       
4685        for (i = 0; i < ntotalCoefs; i += 1)
4686                if (OKToSaveLinkCells || !IsLinkText(CoefListWave[i][1]))
4687                        if ( SaveOnlySelectedCells && !IsRowSelected(CoefSelWave, i) )
4688                                continue
4689                        endif
4690                        if (col == 3)
4691                                w[waveIndex] = ((CoefSelWave[i][col] & 0x10) != 0)
4692                        else
4693                                w[waveIndex] = str2num(CoefListWave[i][col])
4694                        endif
4695                        waveIndex += 1
4696                endif
4697        endfor
4698end
4699
4700static Function FindSelectedRows(SelectionWave)
4701        Wave SelectionWave
4702       
4703        Variable rows = DimSize(SelectionWave, 0)
4704        Variable cols = DimSize(SelectionWave, 1)
4705        Variable i,j
4706        Variable rowsSelected = 0
4707       
4708        for (i = 0; i < rows; i += 1)
4709                for (j = 0; j < cols; j += 1)
4710                        if (IsRowSelected(SelectionWave, i))
4711                                rowsSelected += 1
4712                                break;
4713                        endif
4714                endfor
4715        endfor
4716       
4717        return rowsSelected;
4718end
4719
4720static Function IsRowSelected(SelectionWave, row)
4721        Wave SelectionWave
4722        Variable row
4723       
4724        Variable cols = DimSize(SelectionWave, 1)
4725        Variable j
4726       
4727        for (j = 0; j < cols; j += 1)
4728                if (SelectionWave[row][j] & 9)
4729                        return 1
4730                        break;
4731                endif
4732        endfor
4733       
4734        return 0;
4735end
4736
4737//SRK - new function to generate a report (always)
4738Function Generate_GF_Report(topGraph,GF_resultStr)
4739        String topGraph,GF_resultStr
4740       
4741        String nb = "GF_Report"
4742        String str=""
4743       
4744        // bring report up
4745        DoWindow/F GF_Report
4746        if (V_flag == 0)                // Report notebook doesn't exist ?
4747                NewNotebook/W=(10,45,550,620)/F=1/N=GF_Report as "Global Fit Report"
4748        endif
4749        // delete old stuff
4750        Notebook $nb selection={startOfFile, endOfFile}, text="\r", selection={startOfFile, startOfFile}
4751       
4752        //setup
4753        Notebook $nb defaultTab=36, statusWidth=252, pageMargins={44,44,44,44}          //44 points = 0.6" margin all around
4754        Notebook $nb showRuler=1, rulerUnits=1, updating={1, 60}
4755        Notebook $nb newRuler=Normal, justification=0, margins={0,0,524}, spacing={0,0,0}, tabs={}, rulerDefaults={"Geneva",10,0,(0,0,0)}
4756//     
4757        // insert title
4758        Notebook $nb newRuler=Title, justification=1, rulerDefaults={"Times", 16, 1, (0, 0, 0)}
4759        sprintf str, "Global Fit Completed %s, %s\r\r",Secs2Date(datetime, 0), time()
4760        Notebook $nb ruler=Title, text=str
4761       
4762        //the text
4763        Notebook $nb ruler=Normal
4764        Notebook $nb  margins={0,0,524}, tabs={63 + 3*8192}
4765        Notebook $nb text=GF_resultStr
4766       
4767        //the graph
4768        Notebook $nb picture={$topGraph(0, 0, 400, 300), 0, 1}, text="\r"
4769       
4770        // show the top of the report
4771        Notebook $nb  selection= {startOfFile, startOfFile},  findText={"", 1}
4772       
4773        //save the notebook and the graphic file
4774//      if(yesSave)
4775                String dataFileStr="",nameStr
4776                sscanf StringFromList(4,GF_ResultStr,"\r"),"Data Set:%s",dataFileStr            //reads the 5th line to find the data set name
4777//              String nameStr=CleanupName(func,0)
4778//              nameStr = nameStr[0,8]  //shorten the name
4779                nameStr = "GF_"+dataFileStr
4780                //make sure the name is no more than 31 characters
4781                namestr = namestr[0,30]         //if shorter than 31, this will NOT pad to 31 characters
4782                Print "file saved as ",nameStr
4783                SaveNotebook /O/P=home/S=2 $nb as nameStr
4784//              //save the graph separately as a PICT file, 2x screen
4785//              pictStr += nameStr
4786//              pictStr = pictStr[0,28]         //need a shorter name - why?
4787////            DoWindow/F $topGraph
4788//              // E=-5 is png @screen resolution
4789//              // E=2 is PICT @2x screen resolution
4790/////           SavePICT /E=-5/O/P=home /I/W=(0,0,3,3) as pictStr
4791//              SavePICT /E=-5/O/P=home/WIN=$topGraph /W=(0,0,400,300) as pictStr
4792//      Endif
4793       
4794        return(0)
4795end
4796
4797
4798
4799
Note: See TracBrowser for help on using the repository browser.