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

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

Added the Write Model Data item back to the SANS Models menu, and it now will filter and find the "GFit" generated fits that are deposited in each data folder.

File size: 160.4 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                       
1119        String topGraph= WinName(0,1)
1120        Generate_GF_Report(topGraph,GF_resultStr)
1121       
1122        //eSRK
1123       
1124        return 0
1125end
1126
1127static constant GF_FuncType_Regular = 0
1128static constant GF_FuncType_AllAtOnce = 1
1129static constant GF_FuncType_BadFunc = -1
1130static constant GF_FuncType_NoFunc = -2
1131//SRK
1132static constant GF_FuncType_AAOStruct = 2
1133//eSRK
1134
1135//SRK - modified logic to detect my struct functions (which are also AAO)
1136// and return a new value
1137static Function GF_FunctionType(functionName)
1138        String functionName
1139       
1140        Variable FuncType = GF_FuncType_BadFunc
1141               
1142        string FitFuncs = FunctionList("*", ";", "VALTYPE:1,NPARAMS:2")
1143//      print FitFuncs
1144        if (FindListItem(functionName, FitFuncs) >= 0)
1145                FuncType = GF_FuncType_Regular
1146        else
1147                FitFuncs = FunctionList("*", ";", "VALTYPE:1,NPARAMS:3")
1148                if (FindListItem(functionName, FitFuncs) >= 0)
1149                        FuncType = GF_FuncType_AllAtOnce
1150                endif
1151        endif
1152       
1153        //SRK - still not found, try one param, this would be struct
1154        if (FuncType == GF_FuncType_BadFunc)
1155                FitFuncs = FunctionList("*", ";", "VALTYPE:1,NPARAMS:1")
1156                if (FindListItem(functionName, FitFuncs) >= 0)
1157                        FuncType = GF_FuncType_AAOStruct
1158                endif
1159        endif
1160        //eSRK
1161       
1162        if (FuncType == GF_FuncType_BadFunc)
1163                Variable funcExists = Exists(functionName)
1164                if ((funcExists != 6) && (funcExists != 3) )
1165                        FuncType = GF_FuncType_NoFunc
1166                endif
1167        endif
1168        return FuncType
1169end
1170
1171static Function FirstUseOfIndexInLinkMatrix(index, linkMatrix, row, col)
1172        Variable index
1173        Wave linkMatrix
1174        Variable &row
1175        Variable &col
1176       
1177        Variable i, j
1178        Variable numRows = DimSize(linkMatrix, 0)
1179        Variable numCols = DimSize(linkMatrix, 1)
1180        for (i = 0; i < numRows; i += 1)
1181                for (j = FirstCoefCol; j < numCols; j += 1)
1182                        if (linkMatrix[i][j] == index)
1183                                row = i
1184                                col = j
1185                                return 0
1186                        endif
1187                endfor
1188        endfor
1189       
1190        row = -1
1191        col = -1
1192        return -1
1193end
1194
1195// Checks list of data sets for consistency, etc.
1196// Makes the cumulative data set waves.
1197static Function NewGF_CheckDSets_BuildCumWaves(DataSets, linkageMatrix, doWeighting, doMasking, errorWaveName, errorWaveRow, errorWaveColumn)
1198        Wave/T DataSets
1199        Wave linkageMatrix
1200        Variable &doWeighting
1201        Variable &doMasking
1202        String &errorWaveName
1203        Variable &errorWaveRow
1204        Variable &errorWaveColumn
1205       
1206        errorWaveName = ""
1207
1208        Variable i, j
1209        String XSet, YSet
1210        Variable numSets = DimSize(DataSets, 0)
1211        Variable wavePoints
1212        Variable npnts
1213       
1214        if (numSets == 0)
1215                return 0
1216        endif
1217       
1218        Variable totalPoints = 0
1219       
1220        Variable MaskCol = FindDimLabel(DataSets, 1, "Masks")
1221        doMasking = 0
1222        if (MaskCol >= 0)
1223//              Make/D/N=(totalPoints)/O root:Packages:NewGlobalFit:GFMaskWave
1224                doMasking = 1
1225        endif
1226
1227        doWeighting = 0
1228        Variable WeightCol = FindDimLabel(DataSets, 1, "Weights")
1229        if (WeightCol >= 0)
1230//              Make/D/N=(totalPoints)/O root:Packages:NewGlobalFit:GFWeightWave
1231                doWeighting = 1
1232        endif
1233       
1234        // pre-scan to find the total number of points. This is done so that the concatenated wave
1235        // can be made at the final size all at one time, avoiding problems with virtual memory
1236        // that can be caused by re-sizing a memory block many times.
1237       
1238        // JW 040818 Failing to check for NaN's in the data waves causes a failure of synchronization between
1239        // the data structures and the data passed to the fit function by FuncFit. I will have to check for NaN's
1240        // and not include them.
1241        // I am removing the check for masked points in this loop. If there are masked points or NaN's, the wave
1242        // 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
1243        // points so that I don't have to clutter up the second loop with checks.
1244        for (i = 0; i < numSets; i += 1)
1245                // check the Y wave
1246                YSet = DataSets[i][0]
1247                XSet = DataSets[i][1]
1248                Wave/Z Ysetw = $YSet
1249                Wave/Z Xsetw = $XSet
1250                if (!WaveExists(YSetw))
1251                        errorWaveName = YSet
1252                        errorWaveRow = i
1253                        errorWaveColumn = 0
1254                        return NewGlobalFitBAD_YWAVE
1255                endif
1256                wavePoints = numpnts(Ysetw)
1257               
1258                // check the X wave
1259                if (cmpstr(XSet, "_Calculated_") != 0)
1260                        if (!WaveExists(Xsetw))
1261                                errorWaveName = XSet
1262                                errorWaveRow = i
1263                                errorWaveColumn = 1
1264                                return NewGlobalFitBAD_XWAVE
1265                        endif
1266                        if (wavePoints != numpnts(Xsetw))
1267                                errorWaveRow = i
1268                                errorWaveColumn = 1
1269                                return NewGlobalFitXWaveBADPOINTS
1270                        endif
1271                endif           
1272               
1273                // check mask wave if necessary
1274                if (doMasking)
1275                        Wave/Z mw = $(DataSets[i][MaskCol])
1276                        if (!WaveExists(mw))
1277                                errorWaveRow = i
1278                                errorWaveColumn = MaskCol
1279                                return NewGlobalFitNOMSKWAVE
1280                        endif
1281                        if (wavePoints != numpnts(mw))
1282                                errorWaveRow = i
1283                                errorWaveColumn = MaskCol
1284                                return NewGlobalFitMSKWAVEBADPOINTS
1285                        endif
1286                endif
1287               
1288                // check weighting wave if necessary
1289                if (doWeighting)
1290                        Wave/Z ww = $(DataSets[i][WeightCol])
1291                        if (!WaveExists(ww))
1292                                errorWaveRow = i
1293                                errorWaveColumn = WeightCol
1294                                return NewGlobalFitNOWTWAVE
1295                        endif
1296                        if (wavePoints != numpnts(ww))
1297                                errorWaveRow = i
1298                                errorWaveColumn = WeightCol
1299                                return NewGlobalFitWTWAVEBADPOINTS
1300                        endif
1301                endif
1302
1303                totalPoints += numpnts(Ysetw)
1304        endfor
1305       
1306        if (doWeighting)
1307                Make/D/N=(totalPoints)/O root:Packages:NewGlobalFit:GFWeightWave
1308        endif
1309
1310        // make the waves that will contain the concatenated data sets and the wave that points
1311        // to the appropriate row in the data set linkage matrix
1312        Make/D/N=(totalPoints)/O root:Packages:NewGlobalFit:XCumData, root:Packages:NewGlobalFit:YCumData
1313        Make/U/W/N=(totalPoints)/O root:Packages:NewGlobalFit:DataSetPointer
1314       
1315        Wave Xw = root:Packages:NewGlobalFit:XCumData
1316        Wave Yw = root:Packages:NewGlobalFit:YCumData
1317        Wave DataSetPointer = root:Packages:NewGlobalFit:DataSetPointer
1318        Wave/Z Weightw = root:Packages:NewGlobalFit:GFWeightWave
1319//      Wave/Z Maskw = root:Packages:NewGlobalFit:GFMaskWave
1320       
1321        Variable realTotalPoints = 0
1322        Variable wavePoint = 0
1323
1324        // second pass through the list, this time copying the data into the concatenated sets, and
1325        // setting index numbers in the index wave
1326        for (i = 0; i < numSets; i += 1)
1327                YSet = DataSets[i][0]
1328                XSet = DataSets[i][1]
1329                Wave/Z Ysetw = $YSet
1330                Wave/Z Xsetw = $XSet
1331                Wave/Z mw = $(DataSets[i][MaskCol])
1332                Wave/Z ww = $(DataSets[i][WeightCol])
1333
1334                wavePoints = numpnts(Ysetw)
1335                for (j = 0; j < wavePoints; j += 1)
1336                        if (numtype(Ysetw[j]) != 0)
1337                                continue
1338                        endif
1339                       
1340                        if (doMasking)
1341                                if ( (numtype(mw[j]) != 0) || (mw[j] == 0) )
1342                                        continue
1343                                endif
1344                        endif
1345                       
1346                        if (doWeighting)
1347                                if ( (numtype(ww[j]) != 0) || (ww[j] == 0) )
1348                                        continue
1349                                endif
1350                        endif
1351                       
1352                        DataSetPointer[wavePoint] = i
1353                       
1354                        Yw[wavePoint] = Ysetw[j]
1355
1356                        if (cmpstr(XSet, "_Calculated_") == 0)
1357                                Xw[wavePoint] = pnt2x(Ysetw, j)
1358                        else
1359                                if (numtype(Xsetw[j]) != 0)
1360                                        continue
1361                                endif
1362                                Xw[wavePoint] = Xsetw[j]
1363                        endif
1364                       
1365                        if (doWeighting)
1366                                Weightw[wavePoint] = ww[j]
1367                        endif
1368                       
1369                        wavePoint += 1
1370                endfor
1371               
1372                linkageMatrix[i][FirstPointCol] = realTotalPoints
1373                linkageMatrix[i][LastPointCol] = wavePoint-1
1374                realTotalPoints = wavePoint
1375        endfor
1376       
1377        if (totalPoints > realTotalPoints)
1378                Redimension/N=(realTotalPoints) Yw, Xw
1379                if (doWeighting)
1380                        Redimension/N=(realTotalPoints) Weightw
1381                endif                   
1382        endif
1383       
1384        return numSets
1385end
1386
1387//********************
1388//      The GUI part
1389//********************
1390
1391static Function InitNewGlobalFitGlobals()
1392       
1393        String saveFolder = GetDataFolder(1)
1394       
1395        NewDataFolder/O/S root:Packages
1396        NewDataFolder/O/S NewGlobalFit
1397       
1398        Make/O/T/N=(1,4,2) NewGF_DataSetListWave = ""
1399        SetDimLabel 1, 0, 'Y Waves', NewGF_DataSetListWave
1400        SetDimLabel 1, 1, 'X Waves', NewGF_DataSetListWave
1401        SetDimLabel 1, 2, Function, NewGF_DataSetListWave
1402        SetDimLabel 1, 3, '# Coefs', NewGF_DataSetListWave
1403       
1404        Make/O/T/N=(1,1,2) NewGF_MainCoefListWave = ""
1405        SetDimLabel 1, 0, 'Coefs- K0', NewGF_MainCoefListWave
1406
1407        Make/O/N=(1,4,2) NewGF_DataSetListSelWave = 0   
1408
1409        Make/O/N=(1,1,2) NewGF_MainCoefListSelWave = 0
1410        SetDimLabel 2, 1, backColors, NewGF_MainCoefListSelWave
1411        ColorTab2Wave Pastels
1412        Wave M_colors
1413        Duplicate/O M_colors, NewGF_LinkColors
1414        Variable i, index = 0, size = DimSize(M_colors, 0)
1415        for (i = 0; i < size; i += 1)
1416                NewGF_LinkColors[i][] = M_colors[index][q]
1417                index += 149
1418                if (index >= size)
1419                        index -= size
1420                endif
1421        endfor
1422        KillWaves/Z M_colors
1423       
1424        Make/O/T/N=(1,5) NewGF_CoefControlListWave = ""
1425        Make/O/N=(1,5) NewGF_CoefControlListSelWave
1426        SetDimLabel 1, 0, 'Data Set', NewGF_CoefControlListWave
1427        SetDimLabel 1, 1, Name, NewGF_CoefControlListWave
1428        SetDimLabel 1, 2, 'Initial Guess', NewGF_CoefControlListWave
1429        SetDimLabel 1, 3, 'Hold?', NewGF_CoefControlListWave
1430        SetDimLabel 1, 4, Epsilon, NewGF_CoefControlListWave
1431        NewGF_CoefControlListSelWave[][3] = 0x20
1432       
1433        Variable/G NewGF_RebuildCoefListNow = 1
1434       
1435        Variable points = NumVarOrDefault("FitCurvePoints", 200)
1436        Variable/G FitCurvePoints = points
1437       
1438        String setupName = StrVarOrDefault("NewGF_NewSetupName", "NewGlobalFitSetup")
1439        String/G NewGF_NewSetupName = setupName
1440
1441        SetDataFolder $saveFolder
1442end
1443
1444static Function InitNewGlobalFitPanel()
1445
1446        if (wintype("NewGlobalFitPanel") == 0)
1447                InitNewGlobalFitGlobals()
1448                fNewGlobalFitPanel()
1449        else
1450                DoWindow/F NewGlobalFitPanel
1451        endif
1452end
1453
1454static Function UnloadNewGlobalFit()
1455        if (WinType("NewGlobalFitPanel") == 7)
1456                DoWindow/K NewGlobalFitPanel
1457        endif
1458        if (WinType("GlobalFitGraph") != 0)
1459                DoWindow/K GlobalFitGraph
1460        endif
1461        if (WinType("NewGF_GlobalFitConstraintPanel"))
1462                DoWindow/K NewGF_GlobalFitConstraintPanel
1463        endif
1464        if (WinType("NewGF_WeightingPanel"))
1465                DoWindow/K NewGF_WeightingPanel
1466        endif
1467        if (WinType("NewGF_GlobalFitMaskingPanel"))
1468                DoWindow/K NewGF_GlobalFitMaskingPanel
1469        endif
1470        Execute/P "DELETEINCLUDE  <Global Fit 2>"
1471        Execute/P "COMPILEPROCEDURES "
1472        KillDataFolder root:Packages:NewGlobalFit
1473end
1474
1475static constant NewGF_DSList_YWaveCol = 0
1476static constant NewGF_DSList_XWaveCol = 1
1477static constant NewGF_DSList_FuncCol = 2
1478static constant NewGF_DSList_NCoefCol = 3
1479
1480// moved to separate wave
1481//static constant NewGF_DSList_FirstCoefCol = 4
1482static constant NewGF_DSList_FirstCoefCol = 0
1483
1484static Function fNewGlobalFitPanel()
1485
1486        Variable defLeft = 50
1487        Variable defTop = 70
1488        Variable defRight = 719
1489        Variable defBottom = 447
1490       
1491        String fmt="NewPanel/K=1/W=(%s) as \"Global Analysis\""
1492        String cmd = WC_WindowCoordinatesSprintf("NewGlobalFitPanel", fmt, defLeft, defTop, defRight, defBottom, 0)
1493        Execute cmd
1494
1495//      NewPanel/K=1/W=(156,70,829,443) as "Global Analysis"
1496        DoWindow/C NewGlobalFitPanel
1497
1498        DefineGuide Tab0AreaLeft={FL,13}                        // this is changed to FR, 25 when tab 0 is hidden
1499        DefineGuide Tab0AreaRight={FR,-10}
1500        DefineGuide TabAreaTop={FT,28}
1501        DefineGuide TabAreaBottom={FB,-118}
1502        DefineGuide Tab1AreaLeft={FR,25}                        // this is changed to FL and appropriate offset when tab 1 is shown
1503        DefineGuide Tab1AreaRight={FR,800}
1504        DefineGuide GlobalControlAreaTop={FB,-109}
1505       
1506        TabControl NewGF_TabControl,pos={10,7},size={654,255},proc=WM_NewGlobalFit1#NewGF_TabControlProc
1507        TabControl NewGF_TabControl,tabLabel(0)="Data Sets and Functions"
1508        TabControl NewGF_TabControl,tabLabel(1)="Coefficient Control",value= 0
1509       
1510        NewPanel/FG=(Tab0AreaLeft, TabAreaTop, Tab0AreaRight, TabAreaBottom) /HOST=#
1511                RenameWindow #,Tab0ContentPanel
1512                ModifyPanel frameStyle=0, frameInset=0
1513       
1514//              ListBox NewGF_DataSetsList,pos={3,133},size={443,196}, listWave=root:Packages:NewGlobalFit:NewGF_DataSetListWave
1515//              ListBox NewGF_DataSetsList,selWave=root:Packages:NewGlobalFit:NewGF_DataSetListSelWave,proc=WM_NewGlobalFit1#NewGF_DataSetListBoxProc
1516//              ListBox NewGF_DataSetsList,widths={100,100,100,50,90}, mode=10,editStyle=1,frame=4, colorWave = root:Packages:NewGlobalFit:NewGF_LinkColors
1517               
1518                GroupBox NewGF_DataSetsGroup,pos={2,3},size={640,36}
1519       
1520                        TitleBox NewGF_DataSetsGroupTitle,pos={23,14},size={57,12},title="Data Sets:",fSize=10,frame=0
1521                        TitleBox NewGF_DataSetsGroupTitle,fStyle=1
1522
1523                        PopupMenu NewGF_AddDataSetMenu,pos={88,11},size={120,20},proc=WM_NewGlobalFit1#NewGF_AddYWaveMenuProc,title="Add Data Sets"
1524                        PopupMenu NewGF_AddDataSetMenu,mode=0,bodyWidth= 120,value= #"NewGF_YWaveList(1)"
1525
1526                        PopupMenu NewGF_SetDataSetMenu,pos={370,11},size={120,20},proc=WM_NewGlobalFit1#NewGF_SetDataSetMenuProc,title="Set Y Wave"
1527                        PopupMenu NewGF_SetDataSetMenu,mode=0,bodyWidth= 120,value= #"NewGF_YWaveList(0)"
1528
1529                        PopupMenu NewGF_SetXDataSetMenu,pos={229,11},size={120,20},proc=WM_NewGlobalFit1#NewGF_SetXWaveMenuProc,title="Set X Wave"
1530                        PopupMenu NewGF_SetXDataSetMenu,mode=0,bodyWidth= 120,value= #"NewGF_XWaveList()"
1531
1532                        PopupMenu NewGF_RemoveDataSetMenu1,pos={512,11},size={120,20},proc=WM_NewGlobalFit1#NewGF_RemoveDataSetsProc,title="Remove"
1533                        PopupMenu NewGF_RemoveDataSetMenu1,mode=0,bodyWidth= 120,value= #"NewGF_RemoveMenuList()"
1534
1535                PopupMenu NewGF_SetFunctionMenu,pos={7,51},size={120,20},proc=NewGF_SetFuncMenuProc,title="Choose Fit Func"
1536                PopupMenu NewGF_SetFunctionMenu,mode=0,bodyWidth= 120,value= #"NewGF_FitFuncList()"
1537
1538                GroupBox NewGF_CoefficientsGroup,pos={134,43},size={508,36}
1539
1540                        TitleBox NewGF_Tab0CoefficientsTitle,pos={145,54},size={73,12},title="Coefficients:"
1541                        TitleBox NewGF_Tab0CoefficientsTitle,fSize=10,frame=0,fStyle=1
1542
1543                        Button NewGF_LinkCoefsButton,pos={224,51},size={70,20},proc=NewGF_LinkCoefsButtonProc,title="Link"
1544
1545                        Button NewGF_UnLinkCoefsButton,pos={301,51},size={70,20},proc=NewGF_UnLinkCoefsButtonProc,title="Unlink"
1546
1547                        PopupMenu NewGF_SelectAllCoefMenu,pos={378,51},size={124,20},proc=WM_NewGlobalFit1#NewGF_SelectAllCoefMenuProc,title="Select"
1548                        PopupMenu NewGF_SelectAllCoefMenu,mode=0,bodyWidth= 124,value= #"WM_NewGlobalFit1#NewGF_ListFunctionsAndCoefs()"
1549
1550                        PopupMenu NewGF_SelectAlsoCoefMenu,pos={509,51},size={124,20},proc=WM_NewGlobalFit1#NewGF_SelectAllCoefMenuProc,title="Add To Selection"
1551                        PopupMenu NewGF_SelectAlsoCoefMenu,mode=0,bodyWidth= 124,value= #"WM_NewGlobalFit1#NewGF_ListFunctionsAndCoefs()"
1552
1553                GroupBox NewGF_Tab0ListGroup,pos={2,86},size={641,143}
1554
1555                        ListBox NewGF_DataSetsList,pos={4,88},size={300,139},proc=WM_NewGlobalFit1#NewGF_DataSetListBoxProc
1556                        ListBox NewGF_DataSetsList,listWave=root:Packages:NewGlobalFit:NewGF_DataSetListWave
1557                        ListBox NewGF_DataSetsList,selWave=root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
1558                        ListBox NewGF_DataSetsList,mode= 10,editStyle= 1,widths= {81,81,81,42},frame=1,userColumnResize=1
1559       
1560                        ListBox NewGF_Tab0CoefList,pos={305,88},size={336,139},proc=WM_NewGlobalFit1#NewGF_DataSetListBoxProc
1561                        ListBox NewGF_Tab0CoefList,listWave=root:Packages:NewGlobalFit:NewGF_MainCoefListWave
1562                        ListBox NewGF_Tab0CoefList,selWave=root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
1563                        ListBox NewGF_Tab0CoefList,colorWave=root:Packages:NewGlobalFit:NewGF_LinkColors
1564                        ListBox NewGF_Tab0CoefList,mode= 10,editStyle= 1,widths= {100},frame=1,userColumnResize=1
1565
1566        SetActiveSubwindow ##
1567       
1568        NewPanel/W=(119,117,359,351)/FG=(Tab1AreaLeft,TabAreaTop,Tab1AreaRight,TabAreaBottom)/HOST=#
1569                RenameWindow #, Tab1ContentPanel
1570                ModifyPanel frameStyle=0, frameInset=0
1571               
1572                ListBox NewGF_CoefControlList,pos={4,34},size={440,291},proc = WM_NewGlobalFit1#NewGF_CoefListBoxProc,frame=4
1573                ListBox NewGF_CoefControlList,listWave=root:Packages:NewGlobalFit:NewGF_CoefControlListWave
1574                ListBox NewGF_CoefControlList,selWave=root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
1575                ListBox NewGF_CoefControlList,mode= 10,editStyle= 1,widths= {15,15,7,4,5},userColumnResize=1
1576               
1577                TitleBox NewGF_CoefControlIGTitle,pos={135,9},size={75,15},title="Initial guess:"
1578                TitleBox NewGF_CoefControlIGTitle,fSize=12,frame=0,anchor= RC
1579
1580                PopupMenu NewGF_SetCoefsFromWaveMenu,pos={219,7},size={100,20},title="Set from Wave",mode=0,value=NewGF_ListInitGuessWaves(0, 0)
1581                PopupMenu NewGF_SetCoefsFromWaveMenu,proc=NewGF_SetCoefsFromWaveProc
1582
1583                PopupMenu NewGF_SaveCoefstoWaveMenu,pos={343,7},size={100,20},title="Save to Wave",mode=0,value="New Wave...;-;"+NewGF_ListInitGuessWaves(0, 0)
1584                PopupMenu NewGF_SaveCoefstoWaveMenu,proc=NewGF_SaveCoefsToWaveProc
1585
1586        SetActiveSubwindow ##
1587       
1588        DefineGuide GlobalControlAreaLeft={FR,-200}
1589
1590        NewPanel/W=(495,313,643,351)/FG=(FL,GlobalControlAreaTop,FR,FB)/HOST=#
1591                ModifyPanel frameStyle=0, frameInset=0
1592                RenameWindow #,NewGF_GlobalControlArea
1593       
1594                GroupBox NewGF_GlobalGroup,pos={5,3},size={478,101}
1595
1596                        CheckBox NewGF_ConstraintsCheckBox,pos={330,49},size={79,14},proc=WM_NewGlobalFit1#ConstraintsCheckProc,title="Constraints..."
1597                        CheckBox NewGF_ConstraintsCheckBox,value= 0
1598       
1599                        CheckBox NewGF_WeightingCheckBox,pos={330,11},size={70,14},proc=WM_NewGlobalFit1#NewGF_WeightingCheckProc,title="Weighting..."
1600                        CheckBox NewGF_WeightingCheckBox,value= 0
1601       
1602                        CheckBox NewGF_MaskingCheckBox,pos={330,30},size={63,14},proc=WM_NewGlobalFit1#NewGF_MaskingCheckProc,title="Masking..."
1603                        CheckBox NewGF_MaskingCheckBox,value= 0
1604       
1605                        CheckBox NewGF_DoCovarMatrix,pos={190,49},size={102,14},proc=WM_NewGlobalFit1#NewGF_CovMatrixCheckProc,title="Covariance Matrix"
1606                        CheckBox NewGF_DoCovarMatrix,value= 0,disable=2//SRK
1607       
1608                        CheckBox NewGF_CorrelationMatrixCheckBox,pos={212,69},size={103,14},proc=WM_NewGlobalFit1#NewGF_CorMatrixCheckProc,title="Correlation Matrix"
1609                        CheckBox NewGF_CorrelationMatrixCheckBox,value= 0,disable=2//SRK
1610       
1611                        CheckBox NewGF_MakeFitCurvesCheck,pos={12,11},size={118,14},proc=WM_NewGlobalFit1#NewGF_FitCurvesCheckProc,title="Make Fit Curve Waves"
1612                        CheckBox NewGF_MakeFitCurvesCheck,value= 1
1613       
1614                        CheckBox NewGF_AppendResultsCheckbox,pos={34,30},size={143,14},proc=WM_NewGlobalFit1#NewGF_AppendResultsCheckProc,title="And Append Them to Graphs"
1615                        CheckBox NewGF_AppendResultsCheckbox,value=0,disable=2//SRK
1616       
1617                        CheckBox NewGF_DoResidualCheck,pos={34,69},size={104,14},proc=WM_NewGlobalFit1#NewGF_CalcResidualsCheckProc,title="Calculate Residuals"
1618                        CheckBox NewGF_DoResidualCheck,value= 0,disable=2//SRK
1619       
1620                        CheckBox NewGF_DoDestLogSpacingCheck,pos={34,86},size={108,14},title="Logarithmic Spacing"
1621                        CheckBox NewGF_DoDestLogSpacingCheck,value=0,disable=2//SRK
1622
1623                        SetVariable NewGF_SetFitCurveLength,pos={37,49},size={131,15},title="Fit Curve Points:"
1624                        SetVariable NewGF_SetFitCurveLength,limits={2,inf,1},value= root:Packages:NewGlobalFit:FitCurvePoints,bodyWidth= 50,disable=2//SRK
1625       
1626                        CheckBox NewGF_Quiet,pos={190,30},size={98,14},title="No History Output"
1627                        CheckBox NewGF_Quiet,value=0,disable=2//SRK
1628       
1629                        CheckBox NewGF_FitProgressGraphCheckBox,pos={190,11},size={103,14},title="Fit Progress Graph"
1630                        CheckBox NewGF_FitProgressGraphCheckBox,value= 1
1631       
1632                        Button DoFitButton,pos={421,10},size={50,20},proc=WM_NewGlobalFit1#NewGF_DoTheFitButtonProc,title="Fit!"
1633
1634                GroupBox NewGF_SaveSetupGroup,pos={487,3},size={178,101},title="Setup"
1635
1636                        SetVariable NewGF_SaveSetSetName,pos={496,20},size={162,15},title="Name:"
1637                        SetVariable NewGF_SaveSetSetName,value= root:Packages:NewGlobalFit:NewGF_NewSetupName,bodyWidth= 130
1638       
1639                        CheckBox NewGF_StoredSetupOverwriteOKChk,pos={508,39},size={80,14},title="Overwrite OK"
1640                        CheckBox NewGF_StoredSetupOverwriteOKChk,value= 0
1641       
1642                        Button NewGF_SaveSetupButton,pos={605,36},size={50,20},proc=WM_NewGlobalFit1#NewGF_SaveSetupButtonProc,title="Save"
1643       
1644                        PopupMenu NewGF_RestoreSetupMenu,pos={522,78},size={107,20},proc=WM_NewGlobalFit1#NewGF_RestoreSetupMenuProc,title="Restore Setup"
1645                        PopupMenu NewGF_RestoreSetupMenu,mode=0,value= #"WM_NewGlobalFit1#NewGF_ListStoredSetups()"
1646
1647        SetActiveSubwindow ##
1648       
1649        SetWindow NewGlobalFitPanel, hook = WC_WindowCoordinatesHook
1650        SetWindow NewGlobalFitPanel, hook(NewGF_Resize) = NewGF_PanelResizeHook
1651
1652        NewGF_MoveControls()
1653end
1654
1655Function IsMinimized(windowName)
1656        String windowName
1657       
1658        if (strsearch(WinRecreation(windowName, 0), "MoveWindow 0, 0, 0, 0", 0, 2) > 0)
1659                return 1
1660        endif
1661       
1662        return 0
1663end
1664
1665Function NewGF_PanelResizeHook(H_Struct)
1666        STRUCT WMWinHookStruct &H_Struct
1667       
1668        Variable statusCode = 0
1669
1670if (H_Struct.eventCode == 4)
1671        return 0
1672endif
1673//print "event code: ", H_Struct.eventCode, "; Window: ", H_Struct.winName
1674       
1675        switch (H_Struct.eventCode)
1676                case 2:                 // kill
1677                        if (WinType("NewGF_GlobalFitConstraintPanel"))
1678                                DoWindow/K NewGF_GlobalFitConstraintPanel
1679                        endif
1680                        if (WinType("NewGF_WeightingPanel"))
1681                                DoWindow/K NewGF_WeightingPanel
1682                        endif
1683                        if (WinType("NewGF_GlobalFitMaskingPanel"))
1684                                DoWindow/K NewGF_GlobalFitMaskingPanel
1685                        endif
1686                        break
1687                case 6:                 // resize
1688                        if (IsMinimized(H_Struct.winName))
1689                                break;
1690                        endif
1691                        NewGF_MainPanelMinWindowSize()
1692                        NewGF_MoveControls()
1693                        break
1694        endswitch
1695       
1696        return statusCode               // 0 if nothing done, else 1
1697End
1698
1699static constant NewGF_MainPanelMinWidth = 669
1700static constant NewGF_MainPanelMinHeight = 377
1701
1702static constant NewGF_TabWidthMargin = 15
1703static constant NewGF_TabHeightMargin = 122
1704
1705static constant NewGF_Tab0ListGroupWidthMargin  = 5
1706static constant NewGF_Tab0ListGroupHeightMargin = 88
1707
1708static constant NewGF_DataSetListGrpWidthMargin = 341
1709static constant NewGF_DataSetListGrpHghtMargin = 4
1710
1711static constant NewGF_Tab0CoefListTopMargin = 88
1712static constant NewGF_Tab0CoefListLeftMargin = 1
1713static constant NewGF_Tab0CoefListRightMargin = 2
1714
1715static constant NewGF_CoefListWidthMargin = 10
1716static constant NewGF_CoefListHeightMargin = 40
1717
1718// all dimensions are in points
1719static Function NewGF_MainPanelMinWindowSize()
1720
1721        GetWindow NewGlobalFitPanel, wsize
1722        Variable minimized= (V_right == V_left) && (V_bottom==V_top)
1723        if( minimized )
1724                return 0
1725        endif
1726        Variable width= (V_right - V_left)
1727        Variable height= (V_bottom - V_top)
1728        width= max(width, NewGF_MainPanelMinWidth*72/ScreenResolution)
1729        height= max(height, NewGF_MainPanelMinHeight*72/ScreenResolution)
1730        MoveWindow/W=NewGlobalFitPanel V_left, V_top, V_left+width, V_top+height
1731End
1732
1733static Function NewGF_MoveControls()
1734
1735        GetWindow NewGlobalFitPanel wsizeDC
1736        Variable Width = (V_right - V_left)
1737        Variable Height = (V_bottom - V_top)
1738        TabControl NewGF_TabControl, win=NewGlobalFitPanel,size={width-NewGF_TabWidthMargin, height-NewGF_TabHeightMargin}
1739
1740        ControlInfo/W=NewGlobalFitPanel NewGF_TabControl
1741        switch(V_value)
1742                case 0:
1743                        GetWindow NewGlobalFitPanel#Tab0ContentPanel wsizeDC
1744                        Width = (V_right - V_left) - NewGF_Tab0ListGroupWidthMargin
1745                        Height = (V_bottom - V_top) - NewGF_Tab0ListGroupHeightMargin
1746                        GroupBox NewGF_Tab0ListGroup, win=NewGlobalFitPanel#Tab0ContentPanel, size={width, height}
1747                        ControlInfo/W=NewGlobalFitPanel#Tab0ContentPanel NewGF_DataSetsList
1748                        Variable listwidth = V_width            // constant width
1749                        height -= NewGF_DataSetListGrpHghtMargin
1750                        ListBox NewGF_DataSetsList, win=NewGlobalFitPanel#Tab0ContentPanel, size={listwidth, height}
1751                        ControlInfo/W=NewGlobalFitPanel#Tab0ContentPanel NewGF_DataSetsList
1752                        Variable top = V_top
1753                        Variable left = V_Left + V_width + 1
1754                        ControlInfo/W=NewGlobalFitPanel#Tab0ContentPanel NewGF_Tab0ListGroup
1755                        listwidth = V_left + V_width - 2 - left
1756                        ListBox NewGF_Tab0CoefList, win=NewGlobalFitPanel#Tab0ContentPanel, pos={left, top}, size={listwidth, height}
1757                        break;
1758                case 1:
1759                        GetWindow NewGlobalFitPanel#Tab1ContentPanel wsizeDC
1760                        Width = (V_right - V_left)
1761                        Height = (V_bottom - V_top)
1762                        ListBox NewGF_CoefControlList, win=NewGlobalFitPanel#Tab1ContentPanel,size={width-NewGF_CoefListWidthMargin, height-NewGF_CoefListHeightMargin}
1763                        break;
1764        endswitch
1765end
1766
1767static Function/S NewGF_ListStoredSetups()
1768
1769        String SaveDF = GetDataFolder(1)
1770        SetDataFolder root:Packages:
1771       
1772        if (!DataFolderExists("NewGlobalFit_StoredSetups"))
1773                SetDataFolder $saveDF
1774                return "\\M1(No Stored Setups"
1775        endif
1776       
1777        SetDataFolder NewGlobalFit_StoredSetups
1778       
1779        Variable numDFs = CountObjects(":", 4)
1780        if (numDFs == 0)
1781                SetDataFolder $saveDF
1782                return "\\M1(No Stored Setups"
1783        endif
1784       
1785        Variable i
1786        String theList = ""
1787        for (i = 0; i < numDFs; i += 1)
1788                theList += (GetIndexedObjName(":", 4, i)+";")
1789        endfor
1790       
1791        SetDataFolder $saveDF
1792        return theList
1793end
1794
1795
1796static Function NewGF_SaveSetupButtonProc(ctrlName) : ButtonControl
1797        String ctrlName
1798
1799        SVAR NewGF_NewSetupName = root:Packages:NewGlobalFit:NewGF_NewSetupName
1800        String SaveDF = GetDataFolder(1)
1801        SetDataFolder root:Packages:
1802        NewDataFolder/O/S NewGlobalFit_StoredSetups
1803
1804        if (CheckName(NewGF_NewSetupName, 11))
1805                if (DataFolderExists(NewGF_NewSetupName))
1806                        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_StoredSetupOverwriteOKChk
1807                        if (V_value)
1808                                KillDataFolder $NewGF_NewSetupName
1809                        else
1810                                DoAlert 1, "The setup name "+NewGF_NewSetupName+" already exists. Make a unique name and continue?"
1811                                if (V_flag == 1)
1812                                        NewGF_NewSetupName = UniqueName(NewGF_NewSetupName, 11, 0)
1813                                else
1814                                        SetDataFolder $saveDF
1815                                        return 0                                                        // ******* EXIT *********
1816                                endif
1817                        endif
1818                else
1819                        DoAlert 1, "The setup name is not a legal name. Fix it up and continue?"
1820                        if (V_flag == 1)
1821                                NewGF_NewSetupName = CleanupName(NewGF_NewSetupName, 1)
1822                                NewGF_NewSetupName = UniqueName(NewGF_NewSetupName, 11, 0)
1823                        endif
1824                endif
1825        endif
1826        DuplicateDataFolder ::NewGlobalFit, $NewGF_NewSetupName
1827        SetDataFolder $NewGF_NewSetupName
1828       
1829        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_ConstraintsCheckBox
1830        Variable/G DoConstraints = V_value
1831        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_WeightingCheckBox
1832        Variable/G DoWeighting = V_value
1833        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_MaskingCheckBox
1834        Variable/G DoMasking = V_value
1835        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoCovarMatrix
1836        Variable/G DoCovarMatrix = V_value
1837        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_CorrelationMatrixCheckBox
1838        Variable/G DoCorelMatrix = V_value
1839        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_MakeFitCurvesCheck
1840        Variable/G MakeFitCurves = V_value
1841        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_AppendResultsCheckbox
1842        Variable/G AppendResults = V_value
1843        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoResidualCheck
1844        Variable/G DoResiduals = V_value
1845        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoDestLogSpacingCheck
1846        Variable/G DoLogSpacing = V_value
1847        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_Quiet
1848        Variable/G DoQuiet = V_value
1849        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_FitProgressGraphCheckBox
1850        Variable/G DoFitProgressGraph = V_value
1851       
1852        KillWaves/Z YCumData, FitY, NewGF_FitFuncNames, NewGF_LinkageMatrix, NewGF_DataSetsList, NewGF_CoefWave
1853        KillWaves/Z NewGF_CoefficientNames, CoefDataSetLinkage, FitFuncList, DataSetPointer, ScratchCoefs, MasterCoefs, EpsilonWave
1854        KillWaves/Z GFWeightWave, GFMaskWave, GFUI_GlobalFitConstraintWave, Res_YCumData, M_Covar, W_sigma, W_ParamConfidenceInterval
1855        KillWaves/Z M_Correlation, fitXCumData, XCumData
1856       
1857        KillVariables/Z V_Flag, V_FitQuitReason, V_FitError, V_FitNumIters, V_numNaNs, V_numINFs, V_npnts, V_nterms, V_nheld
1858        KillVariables/Z V_startRow, V_endRow, V_startCol, V_endCol, V_chisq
1859       
1860        SetDataFolder $saveDF
1861End
1862
1863static Function NewGF_RestoreSetupMenuProc(PU_Struct) : PopupMenuControl
1864        STRUCT WMPopupAction &PU_Struct
1865
1866        if (PU_Struct.eventCode == 2)                   // mouse up
1867                String saveDF = GetDataFolder(1)
1868               
1869                SetDataFolder root:Packages:NewGlobalFit_StoredSetups:$(PU_Struct.popStr)
1870                Variable i = 0
1871                do
1872                        Wave/Z w = WaveRefIndexed("", i, 4)
1873                        if (!WaveExists(w))
1874                                break
1875                        endif
1876                       
1877                        Duplicate/O w, root:Packages:NewGlobalFit:$(NameOfWave(w))
1878                        i += 1
1879                while (1)
1880               
1881                String vars = VariableList("*", ";", 4)
1882                Variable nv = ItemsInList(vars)
1883                for (i = 0; i < nv; i += 1)
1884                        String varname = StringFromList(i, vars)
1885                        NVAR vv = $varname
1886                        Variable/G root:Packages:NewGlobalFit:$varname = vv
1887                endfor
1888               
1889                String strs = StringList("*", ";")
1890                Variable nstr = ItemsInList(strs)
1891                for (i = 0; i < nstr; i += 1)
1892                        String strname = StringFromList(i, strs)
1893                        SVAR ss = $strname
1894                        String/G root:Packages:NewGlobalFit:$strname = ss
1895                endfor
1896               
1897                SetDataFolder root:Packages:NewGlobalFit
1898                NVAR DoConstraints
1899                CheckBox NewGF_ConstraintsCheckBox,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoConstraints
1900                NVAR DoWeighting
1901                CheckBox NewGF_WeightingCheckBox,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoWeighting
1902                NVAR DoMasking
1903                CheckBox NewGF_MaskingCheckBox,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoMasking
1904                NVAR DoCovarMatrix
1905                CheckBox NewGF_DoCovarMatrix,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoCovarMatrix
1906                NVAR DoCorelMatrix
1907                CheckBox NewGF_CorrelationMatrixCheckBox,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoCorelMatrix
1908                NVAR MakeFitCurves
1909                CheckBox NewGF_MakeFitCurvesCheck,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=MakeFitCurves
1910                NVAR AppendResults
1911                CheckBox NewGF_AppendResultsCheckbox,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=AppendResults
1912                NVAR DoResiduals
1913                CheckBox NewGF_DoResidualCheck,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoResiduals
1914                Variable/G DoLogSpacing = NumVarOrDefault("DoLogSpacing", 0)
1915                CheckBox NewGF_DoDestLogSpacingCheck,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoLogSpacing
1916                NVAR DoQuiet
1917                CheckBox NewGF_Quiet,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoQuiet
1918                NVAR DoFitProgressGraph
1919                CheckBox NewGF_FitProgressGraphCheckBox,win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=DoFitProgressGraph
1920                KillVariables/Z DoConstraints, DoWeighting, DoMasking, DoCovarMatrix, DoCorelMatrix, MakeFitCurves, AppendResults, DoResiduals, DoQuiet, DoFitProgressGraph
1921               
1922                SetDataFolder $saveDF
1923        endif
1924End
1925
1926Function NewGF_SetTabControlContent(whichTab)
1927        Variable whichTab
1928       
1929        switch(whichTab)
1930                case 0:
1931                        DefineGuide/W=NewGlobalFitPanel Tab1AreaLeft={FR,25},Tab1AreaRight={FR,800}
1932                        DefineGuide/W=NewGlobalFitPanel Tab0AreaLeft={FL,13},Tab0AreaRight={FR,-10}
1933                        break;
1934                case 1:
1935                        NVAR/Z NewGF_RebuildCoefListNow = root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow
1936                        if (!NVAR_Exists(NewGF_RebuildCoefListNow) || NewGF_RebuildCoefListNow)
1937                                NewGF_RebuildCoefListWave()
1938                        endif
1939                        DefineGuide/W=NewGlobalFitPanel Tab0AreaLeft={FR,25},Tab0AreaRight={FR,800}
1940                        DefineGuide/W=NewGlobalFitPanel Tab1AreaLeft={FL,13},Tab1AreaRight={FR, -10}
1941                        break;
1942        endswitch
1943        NewGF_MoveControls()
1944end
1945
1946static Function NewGF_TabControlProc(TC_Struct)
1947        STRUCT WMTabControlAction &TC_Struct
1948
1949        if (TC_Struct.eventCode == 2)
1950                NewGF_SetTabControlContent(TC_Struct.tab)
1951        endif
1952End
1953
1954static Function isControlOrRightClick(eventMod)
1955        Variable eventMod
1956       
1957        if (CmpStr(IgorInfo(2), "Macintosh") == 0)
1958                if ( (eventMod & 24) == 16)
1959                        return 1
1960                endif
1961        else
1962                if ( (eventMod & 16) == 16)
1963                        return 1
1964                endif
1965        endif
1966       
1967        return 0
1968end
1969
1970//static Function NewGF_DataSetListBoxProc(ctrlName,row,col,event)
1971//      String ctrlName     // name of this control
1972//      Variable row        // row if click in interior, -1 if click in title
1973//      Variable col        // column number
1974//      Variable event      // event code
1975       
1976static Function NewGF_DataSetListBoxProc(LB_Struct)
1977        STRUCT WMListboxAction &LB_Struct
1978       
1979        Variable numcoefs
1980        String funcName
1981       
1982        if (LB_Struct.eventCode == 7)           // finish edit
1983                if (CmpStr(LB_Struct.ctrlName, "NewGF_Tab0CoefList") == 0)
1984                        return 0
1985                endif
1986                       
1987                if (LB_Struct.col == NewGF_DSList_NCoefCol)
1988                        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
1989                        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
1990                        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
1991                        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
1992                        Variable i,j
1993                        Variable numrows = DimSize(ListWave, 0)
1994                        Variable numcols = DimSize(Listwave, 1)
1995               
1996                        numcoefs = str2num(ListWave[LB_Struct.row][LB_Struct.col][0])
1997                        funcName = ListWave[LB_Struct.row][NewGF_DSList_FuncCol][0]
1998                        Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
1999                       
2000                        if (NumCoefs > DimSize(CoefListWave, 1)-NewGF_DSList_FirstCoefCol)
2001                                Redimension/N=(-1,NumCoefs+NewGF_DSList_FirstCoefCol, -1) CoefListWave, CoefSelWave
2002                                for (i = 1; i < NumCoefs; i += 1)
2003                                        SetDimLabel 1, i+NewGF_DSList_FirstCoefCol,$("K"+num2str(i)), CoefListWave
2004                                endfor
2005                        endif
2006                        for (i = 0; i < numrows; i += 1)
2007                                if (CmpStr(funcName, ListWave[i][NewGF_DSList_FuncCol][0]) == 0)
2008                                        ListWave[i][NewGF_DSList_NCoefCol][0] = num2str(numCoefs)
2009                                        for (j = 0; j < numCoefs; j += 1)
2010                                                if (!IsLinkText(CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]))               // don't change a LINK specification
2011                                                        CoefListWave[i][NewGF_DSList_FirstCoefCol+j] = "r"+num2istr(i)+":K"+num2istr(j)
2012                                                endif
2013                                        endfor
2014                                endif
2015                        endfor
2016                       
2017                        NewGF_CheckCoefsAndReduceDims()
2018                endif
2019        elseif(LB_Struct.eventCode == 1)                // mouse down
2020                        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2021                       
2022                if (LB_Struct.row == -1)
2023                        if (CmpStr(LB_Struct.ctrlName, "NewGF_Tab0CoefList") == 0)
2024                                Wave SelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2025                        else
2026                                Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2027                        endif
2028                        SelWave[][][0] = SelWave[p][q] & ~1                             // de-select everything to make sure we don't leave something selected in another column
2029                        SelWave[][LB_Struct.col][0] = SelWave[p][LB_Struct.col] | 1                     // select all rows
2030                elseif ( (LB_Struct.row >= 0) && (LB_Struct.row < DimSize(SelWave, 0)) )
2031                        if (CmpStr(LB_Struct.ctrlName, "NewGF_Tab0CoefList") == 0)
2032                                return 0
2033                        endif
2034                       
2035//                      if (GetKeyState(0) == 0)                                                                                // no modifier keys
2036                        if (isControlOrRightClick(LB_Struct.eventMod))                          // right-click or ctrl-click
2037                                switch(LB_Struct.col)
2038                                        case NewGF_DSList_YWaveCol:
2039                                                PopupContextualMenu NewGF_YWaveList(-1)
2040                                                if (V_flag > 0)
2041                                                        Wave w = $S_selection
2042                                                        NewGF_SetYWaveForRowInList(w, $"", LB_Struct.row)
2043                                                        SelWave[LB_Struct.row][LB_Struct.col][0] = 0
2044                                                endif
2045                                                break
2046                                        case NewGF_DSList_XWaveCol:
2047                                                Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2048                                                Wave w = $(ListWave[LB_Struct.row][NewGF_DSList_YWaveCol][1])
2049                                                if (WaveExists(w))
2050                                                        String RowsText = num2str(DimSize(w, 0))
2051                                                        PopupContextualMenu "_calculated_;"+WaveList("*",";","MINROWS:"+RowsText+",MAXROWS:"+RowsText+",DIMS:1,CMPLX:0,TEXT:0,BYTE:0,WORD:0,INTEGER:0")
2052                                                        if (V_flag > 0)
2053                                                                Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2054                                                                Wave/Z w = $S_selection
2055                                                                NewGF_SetXWaveInList(w, LB_Struct.row)
2056                                                                SelWave[LB_Struct.row][LB_Struct.col][0] = 0
2057                                                        endif
2058                                                endif
2059                                                break
2060                                        case NewGF_DSList_FuncCol:
2061                                                PopupContextualMenu NewGF_FitFuncList()
2062                                                if (V_flag > 0)
2063                                                        FuncName = S_selection
2064                                                       
2065                                                        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2066                                                        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2067                                                        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2068                                                        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2069                                                       
2070                                                        String CoefList
2071                                                        NumCoefs = GetNumCoefsAndNamesFromFunction(FuncName, coefList)
2072                                                       
2073                                                        if (numType(NumCoefs) == 0)
2074                                                                if (NumCoefs > DimSize(CoefListWave, 1)-NewGF_DSList_FirstCoefCol)
2075                                                                        Redimension/N=(-1,NumCoefs+NewGF_DSList_FirstCoefCol, -1) CoefListWave, CoefSelWave
2076                                                                        for (i = 1; i < NumCoefs; i += 1)
2077                                                                                SetDimLabel 1, i+NewGF_DSList_FirstCoefCol,$("K"+num2str(i)), CoefListWave
2078                                                                        endfor
2079                                                                endif
2080                                                        endif
2081                                                       
2082                                                        Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2083                                                        ListWave[LB_Struct.row][NewGF_DSList_FuncCol][0] = FuncName
2084                                                        if (numType(NumCoefs) == 0)
2085                                                                ListWave[LB_Struct.row][NewGF_DSList_NCoefCol][0] = num2istr(NumCoefs)
2086                                                                for (j = 0; j < NumCoefs; j += 1)
2087                                                                        String coeftitle = StringFromList(j, coefList)
2088                                                                        if (strlen(coeftitle) == 0)
2089                                                                                coeftitle = "r"+num2istr(LB_Struct.row)+":K"+num2istr(j)
2090                                                                        else
2091                                                                                coeftitle = "r"+num2istr(LB_Struct.row)+":"+coeftitle
2092                                                                        endif
2093                                                                        CoefListWave[LB_Struct.row][NewGF_DSList_FirstCoefCol+j] = coeftitle
2094                                                                endfor
2095                                                                SelWave[LB_Struct.row][NewGF_DSList_NCoefCol][0] = 0
2096                                                        else
2097                                                                SelWave[LB_Struct.row][NewGF_DSList_NCoefCol][0] = 2
2098                                                        endif
2099                                                        for (j = j+NewGF_DSList_FirstCoefCol;j < DimSize(ListWave, 1); j += 1)
2100                                                                CoefListWave[LB_Struct.row][j] = ""
2101                                                        endfor
2102                                                       
2103                                                        NewGF_CheckCoefsAndReduceDims()
2104                                                endif
2105                                                break
2106                                endswitch
2107                        endif
2108                endif
2109        elseif ( (LB_Struct.eventCode == 8) || (LB_Struct.eventCode == 10) )            // vertical scroll or programmatically set top row
2110                String otherCtrl = ""
2111                if (CmpStr(LB_Struct.ctrlName, "NewGF_DataSetsList") == 0)
2112                        otherCtrl = "NewGF_Tab0CoefList"
2113                else
2114                        otherCtrl = "NewGF_DataSetsList"
2115                endif
2116                ControlInfo/W=NewGlobalFitPanel#Tab0ContentPanel $otherCtrl
2117//print LB_Struct.ctrlName, otherCtrl, "event = ", LB_Struct.eventCode, "row = ", LB_Struct.row, "V_startRow = ", V_startRow
2118                if (V_startRow != LB_Struct.row)
2119                        ListBox $otherCtrl win=NewGlobalFitPanel#Tab0ContentPanel,row=LB_Struct.row
2120                        DoUpdate
2121                endif
2122        endif
2123End
2124//xstatic constant NewGF_DSList_YWaveCol = 0
2125//xstatic constant NewGF_DSList_XWaveCol = 1
2126//xstatic constant NewGF_DSList_FuncCol = 2
2127//xstatic constant NewGF_DSList_NCoefCol = 3
2128//xstatic constant NewGF_DSList_FirstCoefCol = 4
2129
2130Function NewGF_AddYWaveMenuProc(PU_Struct)
2131        STRUCT WMPopupAction &PU_Struct
2132
2133        Variable i, nInList
2134       
2135        if (PU_Struct.eventCode == 2)                   // mouse up
2136                strswitch (PU_Struct.popStr)
2137                        case "All From Top Graph":
2138                                String tlist = TraceNameList("", ";", 1)
2139                                String tname
2140                                i = 0
2141                                do
2142                                        tname = StringFromList(i, tlist)
2143                                        if (strlen(tname) == 0)
2144                                                break;
2145                                        endif
2146                                       
2147                                        Wave w = TraceNameToWaveRef("", tname)
2148                                        Wave/Z xw = XWaveRefFromTrace("", tname)
2149                                        if (WaveExists(w) && !NewGF_WaveInListAlready(w))
2150                                                NewGF_AddYWaveToList(w, xw)
2151                                        endif
2152                                        i += 1
2153                                while(1)
2154                                break;
2155                        case "All From Top Table":
2156                                do
2157                                        Wave/Z w = WaveRefIndexed(WinName(0, 2), i, 1)
2158                                        if (!WaveExists(w))
2159                                                break;
2160                                        endif
2161                                       
2162                                        NewGF_AddYWaveToList(w, $"")
2163                                        i += 1
2164                                while (1)
2165                                break;
2166                        default:
2167                                Wave/Z w = $(PU_Struct.popStr)
2168                                if (WaveExists(w) && !NewGF_WaveInListAlready(w))
2169                                        NewGF_AddYWaveToList(w, $"")
2170                                endif
2171                                break;
2172                endswitch
2173        endif
2174       
2175        return 0
2176end
2177
2178static Function NewGF_WaveInListAlready(w)
2179        Wave w
2180       
2181        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2182        Variable i
2183        Variable nrows = DimSize(ListWave, 0)
2184        for (i = 0; i < nrows; i += 1)
2185                Wave/Z rowWave = $(ListWave[i][NewGF_DSList_YWaveCol][1])
2186                if (WaveExists(rowWave) && (CmpStr(ListWave[i][NewGF_DSList_YWaveCol][1], GetWavesDataFolder(w, 2)) == 0))
2187                        return 1
2188                endif
2189        endfor
2190       
2191        return 0
2192end
2193
2194static Function NewGF_AddYWaveToList(w, xw)
2195        Wave w
2196        Wave/Z xw
2197       
2198        if (!NewGF_WaveIsSuitable(w))
2199                return 0
2200        endif
2201       
2202        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2203        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2204        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2205        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2206       
2207        Variable nextRow
2208       
2209        if (DimSize(ListWave, 0) == 1)
2210                if (AllFieldsAreBlank(ListWave, 0))
2211                        nextRow = 0
2212                else
2213                        nextRow = 1
2214                endif
2215        else
2216                nextRow = DimSize(ListWave, 0)
2217        endif
2218       
2219        Redimension/N=(nextRow+1, -1, -1) ListWave, SelWave, CoefListWave, CoefSelWave
2220        SelWave[nextRow] = 0
2221        CoefSelWave[nextRow] = 0
2222        SelWave[nextRow][NewGF_DSList_NCoefCol][0] = 2
2223        ListWave[nextRow] = ""
2224        CoefListWave[nextRow] = ""
2225       
2226        NewGF_SetYWaveForRowInList(w, xw, nextRow)
2227       
2228//      ListWave[nextRow][NewGF_DSList_YWaveCol][0] = NameOfWave(w)
2229//      ListWave[nextRow][NewGF_DSList_YWaveCol][1] = GetWavesDataFolder(w, 2)
2230//      if (WaveExists(xw))
2231//              ListWave[nextRow][NewGF_DSList_XWaveCol][0] = NameOfWave(xw)
2232//              ListWave[nextRow][NewGF_DSList_XWaveCol][1] = GetWavesDataFolder(xw, 2)
2233//      else
2234//              ListWave[nextRow][NewGF_DSList_XWaveCol][0] = "_calculated_"
2235//              ListWave[nextRow][NewGF_DSList_XWaveCol][1] = "_calculated_"
2236//      endif
2237       
2238        Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2239end
2240
2241static Function NewGF_SetYWaveForRowInList(w, xw, row)
2242        Wave/Z w
2243        Wave/Z xw
2244        Variable row
2245       
2246        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2247       
2248        if (WaveExists(w))
2249                ListWave[row][NewGF_DSList_YWaveCol][0] = NameOfWave(w)
2250                ListWave[row][NewGF_DSList_YWaveCol][1] = GetWavesDataFolder(w, 2)
2251        else
2252                ListWave[row][NewGF_DSList_YWaveCol][0] = ""                    // this allows us to clear the data set from a row
2253                ListWave[row][NewGF_DSList_YWaveCol][1] = ""
2254        endif
2255        if (WaveExists(xw))
2256                ListWave[row][NewGF_DSList_XWaveCol][0] = NameOfWave(xw)
2257                ListWave[row][NewGF_DSList_XWaveCol][1] = GetWavesDataFolder(xw, 2)
2258        else
2259                ListWave[row][NewGF_DSList_XWaveCol][0] = "_calculated_"
2260                ListWave[row][NewGF_DSList_XWaveCol][1] = "_calculated_"
2261        endif
2262       
2263        // Whatever happens above, something in the list has changed, so we need to flag the change  for the next time the tab changes
2264        NVAR/Z NewGF_RebuildCoefListNow = root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow
2265        if (!NVAR_Exists(NewGF_RebuildCoefListNow))
2266                Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1
2267        endif
2268        NewGF_RebuildCoefListNow = 1
2269end
2270
2271static Function NewGF_SetDataSetMenuProc(PU_Struct)
2272        STRUCT WMPopupAction &PU_Struct
2273
2274        Variable i, j, nInList
2275       
2276        if (PU_Struct.eventCode == 2)                   // mouse up
2277                Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2278                Variable numRows = DimSize(SelWave, 0)
2279
2280                strswitch (PU_Struct.popStr)
2281                        case "From Top Graph":
2282                                String tlist = TraceNameList("", ";", 1)
2283                                String tname
2284                                i = 0; j = 0
2285                                for (j = 0; j < numRows; j += 1)
2286                                        if ( (SelWave[j][NewGF_DSList_YWaveCol] & 9) != 0)
2287                                                NewGF_SetYWaveForRowInList($"", $"", j)
2288                                        endif
2289                                endfor
2290                                for (j = 0; j < numRows; j += 1)
2291                                        if ( (SelWave[j][NewGF_DSList_YWaveCol] & 9) != 0)
2292                                                tname = StringFromList(i, tlist)
2293                                                if (strlen(tname) == 0)
2294                                                        break;
2295                                                endif
2296                                               
2297                                                Wave w = TraceNameToWaveRef("", tname)
2298                                                Wave/Z xw = XWaveRefFromTrace("", tname)
2299                                                if (WaveExists(w))
2300                                                        if  (!NewGF_WaveInListAlready(w))
2301                                                                NewGF_SetYWaveForRowInList(w, xw, j)
2302                                                        else
2303                                                                j -= 1          // we didn't use this row, so counteract the increment for loop (??)
2304                                                        endif
2305                                                endif
2306                                                i += 1
2307                                        endif
2308                                endfor
2309                                break;
2310                        case "From Top Table":
2311                                i = 0; j = 0
2312                                for (j = 0; j < numRows; j += 1)
2313                                        if ( (SelWave[j][NewGF_DSList_YWaveCol] & 9) != 0)
2314                                                NewGF_SetYWaveForRowInList($"", $"", j)
2315                                        endif
2316                                endfor
2317                                for (j = 0; j < numRows; j += 1)
2318                                        if ( (SelWave[j][NewGF_DSList_YWaveCol] & 9) != 0)
2319                                                Wave w = WaveRefIndexed(WinName(0, 2), i, 1)
2320                                                if (!WaveExists(w))
2321                                                        break;
2322                                                endif
2323                                               
2324                                                NewGF_SetYWaveForRowInList(w, $"", j)
2325                                                i += 1
2326                                        endif
2327                                endfor
2328                                break;
2329                        default:
2330                                Wave/Z w = $(PU_Struct.popStr)
2331                                if (WaveExists(w) && !NewGF_WaveInListAlready(w))
2332                                        for (j = 0; j < numRows; j += 1)
2333                                                if ( (SelWave[j][NewGF_DSList_YWaveCol] & 9) != 0)
2334                                                        NewGF_SetYWaveForRowInList($"", $"", j)
2335                                                        NewGF_SetYWaveForRowInList(w, $"", j)
2336                                                        break                           // a data set should appear in the list only once
2337                                                endif
2338                                        endfor
2339                                endif
2340                                break;
2341                endswitch
2342        endif
2343       
2344        return 0
2345End
2346
2347Function NewGF_SetXWaveInList(w, row)
2348        Wave/Z w
2349        Variable row
2350       
2351        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2352        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2353       
2354        if (WaveExists(w))
2355                Wave/Z yWave = $(ListWave[row][NewGF_DSList_YWaveCol][1])
2356                if (WaveExists(yWave))
2357                        if (DimSize(yWave, 0) != DimSize(w, 0))
2358                                DoAlert 0, "The wave "+NameOfWave(yWave)+"in row "+num2istr(row)+" has different number of point from the X wave "+NameOfWave(w)
2359                                return -1
2360                        endif
2361                endif
2362               
2363                ListWave[row][NewGF_DSList_XWaveCol][0] = NameOfWave(w)
2364                ListWave[row][NewGF_DSList_XWaveCol][1] = GetWavesDataFolder(w, 2)
2365        else
2366                ListWave[row][NewGF_DSList_XWaveCol][0] = "_calculated_"
2367                ListWave[row][NewGF_DSList_XWaveCol][1] = "_calculated_"
2368        endif
2369       
2370        // Whatever happens above, something in the list has changed, so we need to flag the change  for the next time the tab changes
2371        NVAR/Z NewGF_RebuildCoefListNow = root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow
2372        if (!NVAR_Exists(NewGF_RebuildCoefListNow))
2373                Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1
2374        endif
2375        NewGF_RebuildCoefListNow = 1
2376end
2377
2378static Function AllFieldsAreBlank(w, row)
2379        Wave/T w
2380        Variable row
2381       
2382        Variable i
2383        Variable lastRow = DimSize(w, 1)
2384        for (i  = 0; i < lastRow; i += 1)
2385                if (strlen(w[row][i][0]) != 0)
2386                        return 0
2387                endif
2388        endfor
2389       
2390        return 1
2391end
2392
2393static Function NewGF_WaveIsSuitable(w)
2394        Wave w
2395       
2396        String wname = NameOfWave(w)
2397       
2398        if (CmpStr(wname[0,3], "fit_") == 0)
2399                return 0
2400        endif
2401        if (CmpStr(wname[0,3], "res_") == 0)
2402                return 0
2403        endif
2404        if (CmpStr(wname[0,4], "GFit_") == 0)
2405                return 0
2406        endif
2407        if (CmpStr(wname[0,4], "GRes_") == 0)
2408                return 0
2409        endif
2410       
2411        return 1
2412end
2413
2414static Function NewGF_SetXWaveMenuProc(PU_Struct)
2415        STRUCT WMPopupAction &PU_Struct
2416
2417//For a PopupMenu control, the WMPopupAction structure has members as described in the following table:
2418//WMPopupAction Structure Members       
2419//Member        Description
2420//char ctrlName[MAX_OBJ_NAME+1] Control name.
2421//char win[MAX_WIN_PATH+1]      Host (sub)window.
2422//STRUCT Rect winRect   Local coordinates of host window.
2423//STRUCT Rect ctrlRect  Enclosing rectangle of the control.
2424//STRUCT Point mouseLoc Mouse location.
2425//Int32 eventCode       Event that caused the procedure to execute. Main event is mouse up=2.
2426//String userdata       Primary (unnamed) user data. If this changes, it is written back automatically.
2427//Int32 popNum  Item number currently selected (1-based).
2428//char popStr[MAXCMDLEN]        Contents of current popup item.
2429
2430        Variable i, nInList, waveindex
2431
2432        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2433        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2434        Variable numListrows = DimSize(ListWave, 0)
2435       
2436        if (PU_Struct.eventCode == 2)                   // mouse up
2437                strswitch (PU_Struct.popStr)
2438                        case "Top Table to List":
2439                                for (i = 0; i < numListrows; i += 1)
2440                                        Wave/Z w = WaveRefIndexed(WinName(0, 2), i, 1)
2441                                        if (!WaveExists(w))
2442                                                break;
2443                                        endif
2444                                       
2445                                        if (NewGF_SetXWaveInList(w, i))
2446                                                break
2447                                        endif
2448                                endfor
2449                                break;
2450                        case "Top Table to Selection":
2451                                waveindex = 0
2452                                for (i = 0; i < numListrows; i += 1)
2453                                        if (SelWave[i][NewGF_DSList_XWaveCol][0] & 9)
2454                                                Wave/Z w = WaveRefIndexed(WinName(0, 2), waveindex, 1)
2455                                                if (!WaveExists(w))
2456                                                        break;
2457                                                endif
2458                                                if (NewGF_SetXWaveInList(w, i))
2459                                                        break
2460                                                endif
2461                                                waveindex += 1
2462                                        endif
2463                                endfor
2464                                break;
2465                        case "Set All to _calculated_":
2466                                for (i = 0; i < numListrows; i += 1)
2467                                        ListWave[i][NewGF_DSList_XWaveCol] = "_calculated_"
2468                                endfor
2469                                break;
2470                        case "Set Selection to _calculated_":
2471                                for (i = 0; i < numListrows; i += 1)
2472                                        if (SelWave[i][NewGF_DSList_XWaveCol][0] & 9)
2473                                                ListWave[i][NewGF_DSList_XWaveCol] = "_calculated_"
2474                                        endif
2475                                endfor
2476                                break;
2477                        default:
2478                                Wave/Z w = $PU_Struct.popStr
2479                                if (WaveExists(w))
2480                                        for (i = 0; i < numListrows; i += 1)
2481                                                if (SelWave[i][NewGF_DSList_XWaveCol][0] & 9)
2482                                                        NewGF_SetXWaveInList(w, i)
2483                                                        //break
2484                                                endif
2485                                        endfor
2486                                endif
2487                                break;
2488                endswitch
2489        endif
2490       
2491        return 0
2492end
2493
2494static Function NewGF_RemoveDataSetsProc(PU_Struct)
2495        STRUCT WMPopupAction &PU_Struct
2496
2497        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2498        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2499        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2500        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2501       
2502        Variable i,j
2503        Variable ncols = DimSize(ListWave, 1)
2504        Variable nrows = DimSize(ListWave, 0)
2505       
2506        if (PU_Struct.eventCode == 2)                   // mouse up
2507                strswitch (PU_Struct.popStr)
2508                        case "Remove All":
2509                                Redimension/N=(1, 4, -1) ListWave, SelWave
2510                                Redimension/N=(1, 1, -1) CoefListWave, CoefSelWave
2511                                ListWave = ""
2512                                CoefListWave = ""
2513                                SelWave = 0
2514                                CoefSelWave = 0
2515                                Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2516                                break
2517                        case "Remove Selection":
2518                                for (i = nrows-1; i >= 0; i -= 1)
2519                                        for (j = 0; j < ncols; j += 1)
2520                                                if (SelWave[i][j][0] & 9)
2521                                                        DeletePoints i, 1, ListWave, SelWave, CoefListWave, CoefSelWave
2522                                                        Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2523                                                        break
2524                                                endif
2525                                        endfor
2526                                endfor
2527                                break
2528                        default:
2529                                for (i = 0; i < nrows; i += 1)
2530                                        if (CmpStr(PU_Struct.popStr, ListWave[i][NewGF_DSList_YWaveCol][0]) == 0)
2531                                                DeletePoints i, 1, ListWave, SelWave, CoefListWave, CoefSelWave
2532                                                Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2533                                                break
2534                                        endif
2535                                endfor
2536                                break
2537                endswitch
2538        endif
2539end
2540
2541Function NewGF_FitFuncSetSelecRadioProc(ctrlName,checked) : CheckBoxControl
2542        String ctrlName
2543        Variable checked
2544
2545        Variable SetSelect = (CmpStr(ctrlName, "NewGF_FitFuncSetSelectionRadio") == 0) ^ checked
2546       
2547        CheckBox NewGF_FitFuncSetSelectionRadio, win=NewGlobalFitPanel#Tab0ContentPanel, value = SetSelect
2548       
2549        CheckBox NewGF_FitFuncSetAllRadio, win=NewGlobalFitPanel#Tab0ContentPanel, value = !SetSelect
2550End
2551
2552static Function NewGF_CheckCoefsAndReduceDims()
2553        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2554        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2555        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2556        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2557
2558        Variable i
2559        Variable numListRows = DimSize(ListWave, 0)
2560        Variable maxCoefs = 0
2561       
2562        // collect the maximum number of coefficients from the # Coefs column
2563        for (i = 0; i < numListRows; i += 1)
2564                Variable numCoefs = str2num(ListWave[i][NewGF_DSList_NCoefCol])
2565                maxCoefs = max(maxCoefs, numCoefs)
2566        endfor
2567       
2568        if (maxCoefs < DimSize(CoefListWave, 1)-NewGF_DSList_FirstCoefCol)
2569                Variable needCols = maxCoefs + NewGF_DSList_FirstCoefCol
2570                DeletePoints/M=1 needCols, DimSize(CoefListWave, 1)-needCols, CoefListWave, CoefSelWave
2571        endif
2572end
2573
2574Function NewGF_SetFuncMenuProc(PU_Struct)
2575        STRUCT WMPopupAction &PU_Struct
2576
2577        if (PU_Struct.eventCode == 2)                   // mouse up
2578       
2579                Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2580                Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2581                Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2582                Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2583               
2584                Variable numListrows = DimSize(ListWave, 0)
2585                String CoefList
2586                Variable NumCoefs = GetNumCoefsAndNamesFromFunction(PU_Struct.popStr, coefList)
2587                Variable i, j
2588               
2589//              ControlInfo NewGF_FitFuncSetSelectionRadio
2590//              Variable SetSelection = V_value
2591               
2592                if (numType(NumCoefs) == 0)
2593                        if (NumCoefs > DimSize(CoefListWave, 1)-NewGF_DSList_FirstCoefCol)
2594                                Redimension/N=(-1,NumCoefs+NewGF_DSList_FirstCoefCol, -1) CoefListWave, CoefSelWave
2595                                for (i = 1; i < NumCoefs; i += 1)
2596                                        SetDimLabel 1, i+NewGF_DSList_FirstCoefCol,$("K"+num2str(i)), CoefListWave
2597                                endfor
2598                        endif
2599                endif
2600               
2601                for (i = 0; i < numListRows; i += 1)
2602                        if ((SelWave[i][NewGF_DSList_FuncCol][0] & 9) == 0)
2603                                continue                // skip unselected rows
2604                        endif
2605                       
2606                        Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2607                        ListWave[i][NewGF_DSList_FuncCol][0] = PU_Struct.popStr
2608                        if (numType(NumCoefs) == 0)
2609                                ListWave[i][NewGF_DSList_NCoefCol][0] = num2istr(NumCoefs)
2610                                for (j = 0; j < NumCoefs; j += 1)
2611                                        String coeftitle = StringFromList(j, coefList)
2612                                        if (strlen(coeftitle) == 0)
2613                                                coeftitle = "r"+num2istr(i)+":K"+num2istr(j)
2614                                        else
2615                                                coeftitle = "r"+num2istr(i)+":"+coeftitle
2616                                        endif
2617                                        CoefListWave[i][NewGF_DSList_FirstCoefCol+j] = coeftitle
2618                                endfor
2619                                SelWave[i][NewGF_DSList_NCoefCol][0] = 0
2620                        else
2621                                SelWave[i][NewGF_DSList_NCoefCol][0] = 2
2622                        endif
2623                endfor
2624               
2625                NewGF_CheckCoefsAndReduceDims()
2626        endif
2627end
2628
2629Function NewGF_LinkCoefsButtonProc(ctrlName) : ButtonControl
2630        String ctrlName
2631
2632        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2633        Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2634        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2635        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2636       
2637        Variable listRows = DimSize(CoefListWave, 0)
2638        Variable listCols = DimSize(CoefListWave, 1)
2639        Variable i,j
2640        String linkCellText = ""
2641        Variable linkrow, linkcol
2642        Variable lastCol
2643        Variable colorIndex = 1
2644
2645        // scan for link color indices in order to set the color index to use this time to the first free color
2646        do
2647                Variable startOver = 0
2648                for (i = 0; i < listRows; i += 1)
2649                        for (j = NewGF_DSList_FirstCoefCol; j < listCols; j += 1)
2650                                if (CoefSelWave[i][j][%backColors] == colorIndex)
2651                                        colorIndex += 1
2652                                        startOver = 1
2653                                        break;
2654                                endif
2655                        endfor
2656                        if (startOver)
2657                                break;
2658                        endif
2659                endfor
2660        while (startOver)
2661       
2662        // 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.
2663        for (i = 0; i < listRows; i += 1)
2664                lastCol = NewGF_DSList_FirstCoefCol + str2num(ListWave[i][NewGF_DSList_NCoefCol][0])
2665                for (j = NewGF_DSList_FirstCoefCol; j < lastCol; j += 1)
2666                        if (CoefSelWave[i][j][0] & 9)
2667                                linkCellText = CoefListWave[i][j][0]
2668                                linkrow = i
2669                                linkcol = j
2670                                if (CoefSelWave[i][j][%backColors] != 0)
2671                                        colorIndex = CoefSelWave[i][j][%backColors]
2672                                endif
2673                                break;
2674                        endif
2675                endfor
2676                if (strlen(linkCellText) > 0)
2677                        break;
2678                endif
2679        endfor
2680        // 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.
2681        if (IsLinkText(linkCellText))
2682                linkCellText = linkCellText[5, strlen(linkCellText)-1]
2683        endif
2684        CoefSelWave[linkrow][linkcol][0] = 0            // de-select the first selected cell
2685       
2686        Wave/T Tab1CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
2687        Wave Tab1CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
2688
2689        Variable accumulatedGuess = 0
2690        Variable numAccumulatedGuesses = 0
2691        Variable linkGuessListIndex = CoefIndexFromTab0CoefRowAndCol(linkrow, linkcol)
2692        Variable initGuess = str2num(Tab1CoefListWave[linkGuessListIndex][2])
2693        if (numtype(initGuess) == 0)
2694                accumulatedGuess += initGuess
2695                numAccumulatedGuesses += 1
2696        endif
2697        string listOfLinkedRows = num2str(linkGuessListIndex)+";"
2698        string tab1LinkCellText = Tab1CoefListWave[linkGuessListIndex][1]
2699       
2700        // now scan from the cell after the first selected cell looking for selected cells to link to the first one
2701        j = linkcol+1
2702        for (i = linkrow; i < listRows; i += 1)
2703                lastCol = NewGF_DSList_FirstCoefCol + str2num(ListWave[i][NewGF_DSList_NCoefCol][0])
2704                do
2705                        if (j >= listCols)
2706                                break
2707                        endif
2708                        if (CoefSelWave[i][j][0] & 9)
2709                                Variable nCoefs = str2num(ListWave[i][NewGF_DSList_NCoefCol][0])
2710                                if (j >= nCoefs)
2711                                        CoefSelWave[i][j][0] = 0                // un-select this cell
2712                                        break                   // this column isn't used for in this row because this function has fewer coefficients than the maximum
2713                                endif
2714                       
2715                                CoefListWave[i][j][0] = "LINK:"+linkCellText
2716                                CoefSelWave[i][j][%backColors] = colorIndex
2717                                CoefSelWave[linkRow][linkCol][%backColors] = colorIndex                                                 // don't want to set the color of this cell unless another cell is linked to it
2718                                CoefSelWave[i][j][0] = 0
2719                                linkGuessListIndex = CoefIndexFromTab0CoefRowAndCol(i, j)
2720                                initGuess = str2num(Tab1CoefListWave[linkGuessListIndex][2])
2721                                if (numtype(initGuess) == 0)
2722                                        accumulatedGuess += initGuess
2723                                        numAccumulatedGuesses += 1
2724                                endif
2725                                Tab1CoefListWave[linkGuessListIndex][1] = "LINK:"+tab1LinkCellText
2726                                Tab1CoefSelWave[linkGuessListIndex][1] = 0
2727                                Tab1CoefSelWave[linkGuessListIndex][2] = 0
2728                                Tab1CoefSelWave[linkGuessListIndex][3] = 0                      // no more checkbox for holding
2729                                listOfLinkedRows += num2str(linkGuessListIndex)+";"
2730//                              Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2731                        endif
2732                                               
2733                        j += 1
2734                while(1)
2735                j = NewGF_DSList_FirstCoefCol
2736        endfor
2737       
2738        // finally, install the average initial guess into all the linked rows in the tab1 coefficient control list
2739        if (numAccumulatedGuesses > 0)
2740                accumulatedGuess /= numAccumulatedGuesses
2741                Variable endindex = ItemsInList(listOfLinkedRows)
2742                for (i = 0; i < endindex; i += 1)
2743                        Tab1CoefListWave[str2num(StringFromList(i, listOfLinkedRows))][2] = num2str(accumulatedGuess)
2744                endfor
2745        endif
2746End
2747
2748// returns the row in the coefficient guess list (tab 1) for a given row and column in the coefficient list on tab 0
2749static Function CoefIndexFromTab0CoefRowAndCol(row, col)
2750        Variable row, col
2751       
2752        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2753
2754        Variable i, j
2755        col -= NewGF_DSList_FirstCoefCol
2756       
2757        Variable coefListIndex = 0
2758        for (i = 0; i < row; i += 1)
2759                coefListIndex += str2num(ListWave[i][NewGF_DSList_NCoefCol][0])
2760        endfor
2761        coefListIndex += col
2762       
2763        return coefListIndex
2764end
2765
2766Function NewGF_UnLinkCoefsButtonProc(ctrlName) : ButtonControl
2767        String ctrlName
2768
2769
2770        Wave/T DataSetListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2771//      Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2772        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2773        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2774
2775        Wave/T Tab1CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
2776        Wave Tab1CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
2777       
2778        Variable listRows = DimSize(CoefListWave, 0)
2779        Variable listCols = DimSize(CoefListWave, 1)
2780        Variable i,j
2781       
2782        for (i = 0; i < listRows; i += 1)
2783                for (j = NewGF_DSList_FirstCoefCol; j < listCols; j += 1)
2784                        if (CoefSelWave[i][j][0] & 9)
2785                                Variable nCoefs = str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
2786                                if (j >= nCoefs)
2787                                        CoefSelWave[i][j][] = 0         // sets color to white AND un-selects
2788                                        continue                        // this column isn't used for in this row because this function has fewer coefficients than the maximum
2789                                endif
2790                                CoefListWave[i][j][0] = CoefListWave[i][j][1]
2791                                CoefSelWave[i][j][] = 0         // sets color to white AND un-selects
2792                                Variable linkGuessListIndex = CoefIndexFromTab0CoefRowAndCol(i, j)
2793                                Tab1CoefSelWave[linkGuessListIndex][1] = 2
2794                                Tab1CoefSelWave[linkGuessListIndex][2] = 2
2795                                Tab1CoefSelWave[linkGuessListIndex][3] = 0x20           // checkbox
2796                                String coefName = CoefNameFromListText(CoefListWave[i][NewGF_DSList_FirstCoefCol + j][1])
2797                                Tab1CoefListWave[linkGuessListIndex][1] = coefName+"["+DataSetListWave[i][NewGF_DSList_FuncCol][0]+"]["+DataSetListWave[i][NewGF_DSList_YWaveCol][1]+"]"        // last part is full path to Y wave
2798
2799//                              Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 1                      // this change invalidates the coefficient list on the Coefficient Control tab
2800                        endif
2801                endfor
2802        endfor
2803End
2804
2805static Function NewGF_SelectAllCoefMenuProc(PU_Struct) : PopupMenuControl
2806        STRUCT WMPopupAction &PU_Struct
2807
2808        if (PU_Struct.eventCode == 2)                   // mouse up
2809                Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2810//              Wave SelWave = root:Packages:NewGlobalFit:NewGF_DataSetListSelWave
2811                Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2812                Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_MainCoefListSelWave
2813                Variable i,j
2814                Variable numRows = DimSize(CoefListWave, 0)
2815               
2816                if (CmpStr(PU_Struct.ctrlName, "NewGF_SelectAllCoefMenu") == 0)
2817                        CoefSelWave[][][0] = CoefSelWave[p][q][0] & ~9          // clear selection if we're not adding to the selection
2818                endif
2819               
2820                String FuncName = FuncNameFromFuncAndCoef(PU_Struct.popstr)
2821                String CoefName = CoefNameFromListText(PU_Struct.popstr)
2822                for (i = 0; i < numRows; i += 1)
2823                        if (CmpStr(FuncName, ListWave[i][NewGF_DSList_FuncCol][0]) == 0)
2824                                Variable nc = str2num(ListWave[i][NewGF_DSList_NCoefCol][0])
2825                                for (j = 0; j < nc; j += 1)
2826                                        if (CmpStr(CoefName, CoefNameFromListText(CoefListWave[i][NewGF_DSList_FirstCoefCol + j][0])) == 0)
2827                                                CoefSelWave[i][NewGF_DSList_FirstCoefCol + j][0] = CoefSelWave[i][NewGF_DSList_FirstCoefCol + j][0] | 1
2828                                        endif
2829                                endfor
2830                        endif
2831                endfor
2832        endif
2833End
2834
2835
2836static Function/S CoefNameFromListText(listText)
2837        String listText
2838       
2839        Variable colonPos = strsearch(listText, ":", inf, 1)            // search backwards
2840        return listText[colonPos+1, strlen(listText)-1]
2841end
2842
2843static Function/S FuncNameFromFuncAndCoef(theText)
2844        String theText
2845       
2846        Variable colonpos = strsearch(theText, ":", 0)
2847        return theText[0, colonPos-1]
2848end
2849
2850static Function/S NewGF_ListFunctionsAndCoefs()
2851
2852        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2853        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
2854        Variable i, j
2855        Variable numRows = DimSize(ListWave, 0)
2856        String theList = ""
2857       
2858        for (i = 0; i < numRows; i += 1)
2859                Variable nCoefs = str2num(ListWave[i][NewGF_DSList_NCoefCol][0])
2860                String FuncName = ListWave[i][NewGF_DSList_FuncCol][0]
2861                for (j = 0; j < nCoefs; j += 1)
2862                        Variable coefIndex = j + NewGF_DSList_FirstCoefCol
2863                        String coefText = CoefListWave[i][coefIndex][0]
2864                        if (!IsLinkText(coefText))
2865                                String theItem = FuncName+":"+CoefNameFromListText(coefText)
2866                                if (WhichListItem(theItem, theList) < 0)
2867                                        theList += theItem+";"
2868                                endif
2869                        endif
2870                endfor
2871        endfor
2872       
2873        return theList
2874end
2875
2876static Function IsWhiteSpaceChar(thechar)
2877        Variable thechar
2878       
2879        Variable spChar = char2num(" ")
2880        Variable tabChar = char2num("\t")
2881
2882        if ( (thechar == spChar) || (thechar == tabChar) )
2883                return 1
2884        else
2885                return 0
2886        endif
2887end
2888
2889static Function IsEndLine(theLine)
2890        String theLine
2891       
2892        Variable i = 0
2893        Variable linelength = strlen(theLine)
2894       
2895        for (i = 0; i < linelength; i += 1)
2896                Variable thechar = char2num(theLine[i])
2897                if (!IsWhiteSpaceChar(thechar))
2898                        break
2899                endif
2900        endfor
2901        if (i == linelength)
2902                return 0
2903        endif
2904        return CmpStr(theLine[i, i+2], "end") == 0
2905end
2906
2907static Function GetNumCoefsAndNamesFromFunction(funcName, coefList)
2908        String funcName
2909        String &coefList
2910       
2911        Variable i
2912        Variable numCoefs
2913        String funcCode = ProcedureText(funcName )
2914       
2915        coefList = ""
2916       
2917        if (strlen(funcCode) == 0)              // an XOP function?
2918                numCoefs = NaN
2919        else
2920                i=0
2921                Variable commentPos
2922                do
2923                        String aLine = StringFromList(i, funcCode, "\r")
2924                        if (IsEndLine(aLine))
2925                                numCoefs = NaN
2926                                break
2927                        endif
2928                        commentPos = strsearch(aLine, "//CurveFitDialog/ Coefficients", 0 , 2)
2929                        if (commentPos >= 0)            // 2 means ignore case
2930                                sscanf aLine[commentPos, inf], "//CurveFitDialog/ Coefficients %d", numCoefs
2931                                i += 1
2932                                break
2933                        endif
2934                        i += 1
2935                while (1)
2936               
2937                if (numType(numCoefs) == 0)
2938                        do
2939                                aLine = StringFromList(i, funcCode, "\r")
2940                                if (IsEndLine(aLine))
2941                                        break
2942                                endif
2943                                commentPos = strsearch(aLine, "//CurveFitDialog/ w[", 0 , 2)
2944                                if (commentPos >= 0)            // 2 means ignore case
2945                                        Variable equalPos = strsearch(aLine[commentPos, inf], "=", 0) + commentPos
2946                                        if (equalPos > 0)
2947                                                equalPos += 1
2948                                                Variable spChar = char2num(" ")
2949                                                Variable tabChar = char2num("\t")
2950                                                do
2951                                                        Variable char = char2num(aLine[equalPos])
2952                                                        if ( (char == spChar) || (char == tabChar) )
2953                                                                equalPos += 1
2954                                                        else
2955                                                                string name
2956                                                                sscanf aLine[equalPos, inf], "%s", name
2957                                                                coefList += name+";"
2958                                                                break
2959                                                        endif
2960                                                while(1)
2961                                        endif
2962                                endif
2963                                i += 1
2964                        while (1)
2965                endif
2966        endif
2967       
2968        return numCoefs
2969end
2970
2971Function/S NewGF_YWaveList(UseAllWord)
2972        Variable UseAllWord                     // 0: "From Top Graph", 1: "All From Top Graph", -1: Don't include top graph and top table options
2973
2974        if (UseAllWord == 1)
2975                String theList = "All From Top Graph;All From Top Table;-;"
2976        elseif (UseAllWord == -1)
2977                theList = ""
2978        else
2979                theList = "From Top Graph;From Top Table;-;"
2980        endif
2981        theList += WaveList("*", ";", "DIMS:1,CMPLX:0,TEXT:0,BYTE:0,WORD:0,INTEGER:0")
2982        return theList
2983end
2984
2985Function/S NewGF_XWaveList()
2986
2987        String theList = "Top Table to List;Top Table to Selection;Set All to _calculated_;Set Selection to _calculated_;-;"
2988        theList += WaveList("*", ";", "DIMS:1,CMPLX:0,TEXT:0,BYTE:0,WORD:0,INTEGER:0")
2989        return theList
2990end
2991
2992Function/S NewGF_RemoveMenuList()
2993
2994        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
2995
2996        String theList = "Remove All;Remove Selection;-;"
2997        Variable i
2998        Variable nrows = DimSize(ListWave, 0)
2999        for (i = 0; i < nrows; i += 1)
3000                theList += (ListWave[i][NewGF_DSList_YWaveCol][0])+";"
3001        endfor
3002       
3003        return theList
3004end
3005
3006//SRK change to exclude XFuncs, my template, and f* functions
3007//
3008Function/S NewGF_FitFuncList()
3009
3010        string theList="", UserFuncs, XFuncs,tmp
3011       
3012        string options = "KIND:10"
3013//      ControlInfo/W=GlobalFitPanel RequireFitFuncCheckbox
3014//      if (V_value)
3015                options += ",SUBTYPE:FitFunc"
3016//      endif
3017        options += ",NINDVARS:1"
3018       
3019        UserFuncs = FunctionList("*", ";",options)
3020        UserFuncs = RemoveFromList("GFFitFuncTemplate", UserFuncs)
3021        UserFuncs = RemoveFromList("GFFitAllAtOnceTemplate", UserFuncs)
3022        UserFuncs = RemoveFromList("NewGlblFitFunc", UserFuncs)
3023        UserFuncs = RemoveFromList("NewGlblFitFuncAllAtOnce", UserFuncs)
3024        UserFuncs = RemoveFromList("GlobalFitFunc", UserFuncs)
3025        UserFuncs = RemoveFromList("GlobalFitAllAtOnce", UserFuncs)
3026        //SRK - remove my template from the list
3027        UserFuncs = RemoveFromList("GFFitAAOStructTemplate", UserFuncs)
3028        tmp = FunctionList("f*",";","NPARAMS:2")                //point calculations
3029        UserFuncs = RemoveFromList(tmp, UserFuncs  ,";")
3030       
3031        tmp = FunctionList("fSmear*",";","NPARAMS:3")           //smeared dependency calculations
3032        UserFuncs = RemoveFromList(tmp, UserFuncs  ,";")
3033        //eSRK
3034
3035//SRK
3036//      XFuncs = FunctionList("*", ";", "KIND:12")
3037        XFuncs = ""
3038//eSRK
3039       
3040        if (strlen(UserFuncs) > 0)
3041                theList +=  "\\M1(   User-defined functions:;"
3042                theList += UserFuncs
3043        endif
3044        if (strlen(XFuncs) > 0)
3045                theList += "\\M1(   External Functions:;"
3046                theList += XFuncs
3047        endif
3048       
3049        if (strlen(theList) == 0)
3050                theList = "\\M1(No Fit Functions"
3051        endif
3052       
3053        //SRK
3054        theList = SortList(theList)
3055        //eSRK
3056        return theList
3057end
3058
3059static Function NewGF_RebuildCoefListWave()
3060
3061        Wave/T DataSetListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3062        Wave/T Tab0CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
3063        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
3064        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
3065       
3066        Variable DSListRows = DimSize(DataSetListWave, 0)
3067        Variable i, j, k
3068        Variable numUnlinkedCoefs = 0
3069        Variable totalCoefs = 0
3070        Variable nc
3071        Variable coefColonPos
3072        Variable colonPos
3073        Variable linkRow
3074       
3075        // count total number of coefficient taking into account linked coefficients
3076        for (i = 0; i < DSListRows; i += 1)
3077                totalCoefs += str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
3078        endfor
3079       
3080        if (numtype(totalCoefs) != 0)
3081                return 0                                                // ****** EXIT ******
3082        endif
3083       
3084        Redimension/N=(totalCoefs, -1, -1) CoefListWave, CoefSelWave
3085        CoefListWave[][2] = ""                  // clear out any initial guesses that might be left over from previous incarnations
3086        CoefSelWave[][3] = 0x20                 // make the new rows have checkboxes in the Hold column
3087        CoefListWave[][3] = ""                  // make the checkboxes have no label
3088        CoefSelWave[][1] = 2                    // make the name column editable
3089        CoefSelWave[][2] = 2                    // make the initial guess column editable
3090        CoefSelWave[][4] = 2                    // make the epsilon column editable
3091        CoefListWave[][4] = "1e-6"              // a reasonable value for epsilon
3092       
3093        Variable coefIndex = 0
3094        for (i = 0; i < DSListRows; i += 1)
3095                nc = str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
3096                for (j = 0; j < nc; j += 1)
3097                        CoefListWave[coefIndex][0] = DataSetListWave[i][NewGF_DSList_YWaveCol][1]                       // use the full path here
3098                        String coefName = CoefNameFromListText(Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol + j][1])
3099                        if (IsLinkText(Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]))
3100                                Variable linkIndex = NewGF_CoefRowForLink(Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0])
3101                                CoefListWave[coefIndex][1] = "LINK:"+CoefListWave[linkIndex][1]
3102                                CoefListWave[coefIndex][2] = CoefListWave[linkIndex][2]
3103                                CoefSelWave[coefIndex][1,] = 0          // not editable- this is a coefficient linked to another
3104                        else
3105                                CoefListWave[coefIndex][1] = coefName+"["+DataSetListWave[i][NewGF_DSList_FuncCol][0]+"]["+DataSetListWave[i][NewGF_DSList_YWaveCol][1]+"]"     // last part is full path to Y wave
3106//                              CoefListWave[coefIndex][1] = DataSetListWave[i][NewGF_DSList_FuncCol][0]+":"+coefText
3107                        endif
3108                        coefIndex += 1
3109                endfor
3110        endfor 
3111       
3112        Variable/G root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow = 0
3113end
3114
3115static Function NewGF_CoefListBoxProc(ctrlName,row,col,event) : ListBoxControl
3116        String ctrlName     // name of this control
3117        Variable row        // row if click in interior, -1 if click in title
3118        Variable col        // column number
3119        Variable event      // event code
3120       
3121        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
3122        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
3123        Wave/T DataSetListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3124        Wave/T Tab0CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
3125
3126        Variable DSListRows = DimSize(DataSetListWave, 0)
3127        Variable i,j
3128        Variable coefIndex = 0
3129        Variable selectionExists
3130        String newName
3131        Variable numRowsNeeded
3132       
3133        // if a coefficient name has been changed, we need to track down any linked coefficients and change them, too.
3134        if ( (event == 7) || (event == 2) )             // finish edit
3135                if ( (col >= 1) || (col <= 4) )         // edited a name, initial guess, hold, or epsilon
3136                        if ( (event == 2) && (col != 3) )
3137                                return 0
3138                        endif
3139                        for (i = 0; i <         DSListRows; i += 1)
3140                                Variable nc = str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
3141                                for (j = 0; j < nc; j += 1)
3142                                        if (IsLinkText(Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]))
3143                                                if (NewGF_CoefListRowForLink(Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]) == row)
3144                                                        switch (col)
3145                                                                case 1:
3146                                                                        CoefListWave[coefIndex][1] = "LINK:"+CoefListWave[row][1]
3147                                                                        break;
3148                                                                case 2:
3149                                                                case 4:
3150                                                                        CoefListWave[coefIndex][col] = CoefListWave[row][col]
3151                                                                        break;
3152                                                                case 3:
3153                                                                        if (CoefSelWave[row][3] & 0x10)         // is it checked?
3154                                                                                CoefListWave[coefIndex][3] = " X"
3155                                                                        else
3156                                                                                CoefListWave[coefIndex][3] = ""
3157                                                                        endif
3158                                                                        break;
3159                                                        endswitch
3160                                                endif
3161                                        endif
3162                                        coefIndex += 1
3163                                endfor
3164                        endfor
3165                endif
3166        elseif ( (event == 1) && (row == -1) && (col >= 2) )
3167                selectionExists = (FindSelectedRows(CoefSelWave) > 0)
3168                string menuStr = "Select All;De-select All;"
3169                if (selectionExists)
3170                        menuStr += "Save Selection to Wave...;Load Selection From Wave...;"
3171                else
3172                        menuStr += "Save to Wave...;Load From Wave...;"
3173                endif
3174                if (col == 3)           // hold column
3175                        menuStr += "Clear all holds;"
3176                endif
3177                PopupContextualMenu menuStr
3178                if (V_flag > 0)
3179                        switch (V_flag)
3180                                case 1:
3181                                        CoefSelWave[][] = CoefSelWave[p][q] & ~9                // clear all selections
3182                                        CoefSelWave[][col] = CoefSelWave[p][col] | 1    // select all in this column
3183                                        break;
3184                                case 2:
3185                                        CoefSelWave[][] = CoefSelWave[p][q] & ~9
3186                                        break;
3187                                case 3:
3188                                        PopupContextualMenu "\\M1(  Save to Wave:;New Wave...;"+NewGF_ListInitGuessWaves(selectionExists, selectionExists)
3189
3190                                        if (V_flag > 0)
3191                                                if (CmpStr(S_selection, "New Wave...") == 0)
3192                                                        numRowsNeeded = selectionExists ? totalSelRealCoefsFromCoefList(1) : totalRealCoefsFromCoefList(0)
3193                                                        newName = NewGF_GetNewWaveName()
3194                                                        if (strlen(newName) == 0)
3195                                                                return 0
3196                                                        endif
3197                                                        Make/O/N=(numRowsNeeded)/D $newName
3198                                                        Wave w = $newName
3199                                                else
3200                                                        Wave w = $(S_selection)
3201                                                endif
3202                                               
3203                                                if (WaveExists(w))
3204                                                        SaveCoefListToWave(w, col, selectionExists, selectionExists)            // SaveOnlySelectedCells, OKToSaveLinkCells
3205                                                endif
3206                                        endif
3207                                        break;
3208                                case 4:
3209                                        selectionExists = (FindSelectedRows(CoefSelWave) > 0)
3210                                        PopupContextualMenu "\\M1(  Load From Wave:;"+NewGF_ListInitGuessWaves(selectionExists, selectionExists)
3211                                        if (V_flag > 0)
3212                                                Wave w = $(S_selection)
3213                                               
3214                                                if (WaveExists(w))
3215                                                        SetCoefListFromWave(w, col, selectionExists, selectionExists)
3216                                                endif
3217                                        endif
3218                                        break;
3219                                case 5:
3220                                        for (i = 0; i < DimSize(CoefSelWave, 0); i += 1)
3221                                                Make/O/N=(DimSize(CoefSelWave, 0)) GFTempHoldWave
3222                                                GFTempHoldWave = 0
3223                                                SetCoefListFromWave(GFTempHoldWave, 3, 0, 0)
3224                                                KillWaves/Z GFTempHoldWave
3225                                        endfor
3226                        endswitch
3227                endif
3228        endif
3229       
3230        return 0
3231end
3232
3233// 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
3234static Function NewGF_CoefRowForLink(linktext)
3235        String linktext
3236       
3237        Wave/T DataSetListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3238        Wave/T Tab0CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
3239
3240        Variable i,j
3241        Variable DSListRows = DimSize(DataSetListWave, 0)
3242        Variable coefIndex = 0;
3243       
3244        for (i = 0; i <         DSListRows; i += 1)
3245                Variable nc = str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
3246                for (j = 0; j < nc; j += 1)
3247                        if (CmpStr((Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]), linktext[5, strlen(linktext)-1]) == 0)
3248                                return coefIndex
3249                        endif
3250                        if (!IsLinkText(Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]))
3251                                coefIndex += 1
3252                        endif
3253                endfor
3254        endfor
3255end
3256
3257static Function NewGF_CoefListRowForLink(linktext)
3258        String linktext
3259       
3260        Wave/T DataSetListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3261        Wave/T Tab0CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
3262
3263        Variable i,j
3264        Variable DSListRows = DimSize(DataSetListWave, 0)
3265        Variable coefIndex = 0;
3266       
3267        for (i = 0; i <         DSListRows; i += 1)
3268                Variable nc = str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
3269                for (j = 0; j < nc; j += 1)
3270                        if (CmpStr((Tab0CoefListWave[i][NewGF_DSList_FirstCoefCol+j][0]), linktext[5, strlen(linktext)-1]) == 0)
3271                                return coefIndex
3272                        endif
3273                        coefIndex += 1
3274                endfor
3275        endfor
3276end
3277
3278
3279//******************************************************
3280// the function that runs when Fit! button is clicked
3281//******************************************************
3282
3283//static constant NewGF_DSList_YWaveCol = 0
3284//static constant NewGF_DSList_XWaveCol = 1
3285//static constant NewGF_DSList_FuncCol = 2
3286//static constant NewGF_DSList_NCoefCol = 3
3287
3288//static constant NewGF_DSList_FirstCoefCol = 0
3289
3290//static constant FuncPointerCol = 0
3291//static constant FirstPointCol = 1
3292//static constant LastPointCol = 2
3293//static constant NumFuncCoefsCol = 3
3294//static constant FirstCoefCol = 4
3295
3296static Function NewGF_DoTheFitButtonProc(ctrlName) : ButtonControl
3297        String ctrlName
3298
3299        Wave/T DataSetListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3300        Wave/T Tab0CoefListWave = root:Packages:NewGlobalFit:NewGF_MainCoefListWave
3301        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
3302        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
3303       
3304        Variable numDataSets = DimSize(DataSetListWave, 0)
3305        Variable numCoefCols = DimSize(Tab0CoefListWave, 1)
3306        Variable i, j
3307        Variable nextFunc = 0
3308
3309        Variable curveFitOptions = 0
3310
3311        // build wave listing Fitting Function names. Have to check for repeats...
3312        Make/O/T/N=(numDataSets) root:Packages:NewGlobalFit:NewGF_FitFuncNames = ""
3313        Wave/T FitFuncNames = root:Packages:NewGlobalFit:NewGF_FitFuncNames
3314       
3315        for (i = 0; i < numDataSets; i += 1)
3316                if (!ItemListedInWave(DataSetListWave[i][NewGF_DSList_FuncCol][0], FitFuncNames))
3317                        FitFuncNames[nextFunc] = DataSetListWave[i][NewGF_DSList_FuncCol][0]
3318                        nextFunc += 1
3319                endif
3320        endfor
3321        Redimension/N=(nextFunc) FitFuncNames
3322       
3323        // build the linkage matrix required by DoNewGlobalFit
3324        // 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
3325        // so here we calculate the number of columns to protect against future changes
3326       
3327        Variable MaxNCoefs = numCoefCols - NewGF_DSList_FirstCoefCol
3328        Variable numLinkageCols = MaxNCoefs + FirstCoefCol
3329       
3330        Make/N=(numDataSets, numLinkageCols)/O root:Packages:NewGlobalFit:NewGF_LinkageMatrix
3331        Wave LinkageMatrix = root:Packages:NewGlobalFit:NewGF_LinkageMatrix
3332       
3333        Variable nRealCoefs = 0         // accumulates the number of independent coefficients (that is, non-link coefficients)
3334        for (i = 0; i < numDataSets; i += 1)
3335                Variable nc = str2num(DataSetListWave[i][NewGF_DSList_NCoefCol][0])
3336
3337                LinkageMatrix[i][FuncPointerCol] = ItemNumberInTextWaveList(DataSetListWave[i][NewGF_DSList_FuncCol][0], FitFuncNames)
3338                LinkageMatrix[i][FirstPointCol] = 0             // this is private info used by DoNewGlobalFit(). It will be filled in by DoNewGlobalFit()
3339                LinkageMatrix[i][LastPointCol] = 0              // this is private info used by DoNewGlobalFit(). It will be filled in by DoNewGlobalFit()
3340                LinkageMatrix[i][NumFuncCoefsCol] = nc
3341               
3342                for (j = NewGF_DSList_FirstCoefCol; j < numCoefCols; j += 1)
3343                        Variable linkMatrixCol = FirstCoefCol + j - NewGF_DSList_FirstCoefCol
3344                        if (j-NewGF_DSList_FirstCoefCol < nc)
3345                                String cellText = Tab0CoefListWave[i][j][0]
3346                                if (IsLinkText(cellText))
3347                                        LinkageMatrix[i][linkMatrixCol] = NewGF_CoefRowForLink(cellText)
3348                                else
3349                                        LinkageMatrix[i][linkMatrixCol] = nRealCoefs
3350                                        nRealCoefs += 1
3351                                endif
3352                        else
3353                                LinkageMatrix[i][linkMatrixCol] = -1
3354                        endif
3355                endfor
3356DoUpdate
3357        endfor
3358       
3359        // Build the data sets list wave
3360        Make/O/T/N=(numDataSets, 2) root:Packages:NewGlobalFit:NewGF_DataSetsList
3361        Wave/T DataSets = root:Packages:NewGlobalFit:NewGF_DataSetsList
3362        DataSets[][0,1] = DataSetListWave[p][q+NewGF_DSList_YWaveCol][1]                // layer 1 contains full paths
3363       
3364        // Add weighting, if necessary
3365        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_WeightingCheckBox
3366        if (V_value)
3367                GFUI_AddWeightWavesToDataSets(DataSets)
3368                NVAR/Z GlobalFit_WeightsAreSD = root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD
3369                if (NVAR_Exists(GlobalFit_WeightsAreSD) && GlobalFit_WeightsAreSD)
3370                        curveFitOptions += NewGFOptionWTISSTD
3371                endif
3372        endif
3373       
3374        // Add Mask, if necessary
3375        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_MaskingCheckBox
3376        if (V_value)
3377                GFUI_AddMaskWavesToDataSets(DataSets)
3378        endif
3379
3380        // Build the Coefficient wave and CoefNames wave
3381        Make/O/D/N=(nRealCoefs, 3) root:Packages:NewGlobalFit:NewGF_CoefWave
3382        Wave coefWave = root:Packages:NewGlobalFit:NewGF_CoefWave
3383        SetDimLabel 1,1,Hold,coefWave
3384        SetDimLabel 1,2,Epsilon,coefWave
3385        Make/O/T/N=(nRealCoefs) root:Packages:NewGlobalFit:NewGF_CoefficientNames
3386        Wave/T CoefNames = root:Packages:NewGlobalFit:NewGF_CoefficientNames
3387
3388        Variable coefIndex = 0
3389        Variable nTotalCoefs = DimSize(CoefListWave, 0)
3390        for (i = 0; i < nTotalCoefs; i += 1)
3391                if (!IsLinkText(CoefListWave[i][1]))
3392                        coefWave[coefIndex][0] = str2num(CoefListWave[i][2])
3393                        if (numtype(coefWave[coefIndex][0]) != 0)
3394                                TabControl NewGF_TabControl, win=NewGlobalFitPanel,value=1
3395                                NewGF_SetTabControlContent(1)
3396                                CoefSelWave = (CoefSelWave & ~1)
3397                                CoefSelWave[i][2] = 3
3398                                DoAlert 0, "There is a problem with the initial guess value in row "+num2str(i)+": it is not a number."
3399                                return -1
3400                        endif
3401                        coefWave[coefIndex][%Hold] = ((CoefSelWave[i][3] & 0x10) != 0)
3402                        coefWave[coefIndex][%Epsilon] = str2num(CoefListWave[i][4])
3403                        if (numtype(coefWave[coefIndex][%Epsilon]) != 0)
3404                                TabControl NewGF_TabControl, win=NewGlobalFitPanel,value=1
3405                                NewGF_SetTabControlContent(1)
3406                                CoefSelWave = (CoefSelWave & ~1)
3407                                CoefSelWave[i][4] = 3
3408                                DoAlert 0, "There is a problem with the Epsilon value in row "+num2str(i)+": it is not a number."
3409                                return -1
3410                        endif
3411                        CoefNames[coefIndex] = CoefListWave[i][1]
3412                        coefIndex += 1
3413                endif
3414        endfor
3415       
3416        // Build constraint wave, if necessary
3417        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_ConstraintsCheckBox
3418        if (V_value)
3419                NewGF_MakeConstraintWave()
3420                Wave/T/Z ConstraintWave = root:Packages:NewGlobalFit:GFUI_GlobalFitConstraintWave
3421        else
3422                Wave/T/Z ConstraintWave = $""
3423        endif
3424       
3425        // Set options
3426        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoCovarMatrix
3427        if (V_value)
3428                curveFitOptions += NewGFOptionCOV_MATRIX
3429        endif
3430
3431        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_CorrelationMatrixCheckBox
3432        if (V_value)
3433                curveFitOptions += NewGFOptionCOR_MATRIX
3434        endif
3435
3436        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_MakeFitCurvesCheck
3437        if (V_value)
3438                curveFitOptions += NewGFOptionMAKE_FIT_WAVES
3439        endif
3440
3441        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea AppendResultsCheck
3442        if (V_value)
3443                curveFitOptions += NewGFOptionAPPEND_RESULTS
3444        endif
3445       
3446        NVAR FitCurvePoints = root:Packages:NewGlobalFit:FitCurvePoints
3447       
3448        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoResidualCheck
3449        if (V_value)
3450                curveFitOptions += NewGFOptionCALC_RESIDS
3451        endif
3452       
3453        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoDestLogSpacingCheck
3454        if (V_value)
3455                curveFitOptions += NewGFOptionLOG_DEST_WAVE
3456        endif
3457       
3458        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_Quiet
3459        if (V_value)
3460                curveFitOptions += NewGFOptionQUIET
3461        endif
3462
3463        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_FitProgressGraphCheckBox
3464        if (V_value)
3465                curveFitOptions += NewGFOptionFIT_GRAPH
3466        endif
3467
3468        Variable err = DoNewGlobalFit(FitFuncNames, DataSets, LinkageMatrix, coefWave, CoefNames, ConstraintWave, curveFitOptions, FitCurvePoints, 1)
3469
3470        if (!err)
3471                SetCoefListFromWave(coefWave, 2, 0, 0)
3472        endif
3473end
3474
3475static Function/S MakeHoldString(CoefWave, quiet, justTheString)
3476        Wave CoefWave
3477        Variable quiet
3478        Variable justTheString
3479       
3480        String HS=""
3481
3482        Variable HoldCol = FindDimLabel(CoefWave, 1, "Hold")
3483        Variable nHolds = 0
3484        if (HoldCol > 0)
3485                if (!justTheString)
3486                        HS="/H=\""
3487                endif
3488                Variable nCoefs=DimSize(CoefWave, 0)
3489                Variable i
3490                for (i = 0; i < nCoefs; i += 1)
3491                        if (CoefWave[i][HoldCol])
3492                                HS += "1"
3493                                nHolds += 1
3494                        else
3495                                HS += "0"
3496                        endif
3497                endfor
3498                if (nHolds == 0)
3499                        return ""                       // ******** EXIT ***********
3500                endif
3501                // work from the end of the string removing extraneous zeroes
3502                if (strlen(HS) > 1)
3503                        for (i = strlen(HS)-1; i >= 0; i -= 1)
3504                                if (CmpStr(HS[i], "1") == 0)
3505                                        break
3506                                endif
3507                        endfor
3508                        if (i > 0)
3509                                HS = HS[0,i]
3510                        endif
3511                endif
3512                if (!justTheString)
3513                        HS += "\""
3514                endif
3515//              if (!quiet)
3516//                      print "Hold String=", HS
3517//              endif
3518                return HS                               // ******** EXIT ***********
3519        else
3520                return ""                               // ******** EXIT ***********
3521        endif
3522end
3523
3524//***********************************
3525//
3526// Constraints
3527//
3528//***********************************
3529
3530static Function ConstraintsCheckProc(ctrlName,checked) : CheckBoxControl
3531        String ctrlName
3532        Variable checked
3533       
3534        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3535        Variable NumSets = DimSize(ListWave, 0)
3536        Variable i
3537
3538        if (checked)
3539                if (NumSets == 0)
3540                        CheckBox NewGF_ConstraintsCheckBox, win=GlobalFitPanel, value=0
3541                        DoAlert 0, "You cannot add constraints until you have selected data sets"
3542                        return 0
3543                else
3544                        NVAR/Z NewGF_RebuildCoefListNow = root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow
3545                        if (!NVAR_Exists(NewGF_RebuildCoefListNow) || NewGF_RebuildCoefListNow)
3546                                NewGF_RebuildCoefListWave()
3547                        endif
3548                        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
3549                        Variable totalParams = 0
3550                        Variable CoefSize = DimSize(CoefListWave, 0)
3551                        for (i = 0; i < CoefSize; i += 1)
3552                                if (!IsLinkText(CoefListWave[i][1]))
3553                                        totalParams += 1
3554                                endif
3555                        endfor
3556
3557                        String saveDF = GetDatafolder(1)
3558                        SetDatafolder root:Packages:NewGlobalFit
3559                       
3560                        Wave/T/Z SimpleConstraintsListWave
3561                        if (!(WaveExists(SimpleConstraintsListWave) && (DimSize(SimpleConstraintsListWave, 0) == TotalParams)))
3562                                Make/O/N=(TotalParams, 5)/T SimpleConstraintsListWave=""
3563                        endif
3564                        Variable CoefIndex = 0
3565                        for (i = 0; i < CoefSize; i += 1)
3566                                if (!IsLinkText(CoefListWave[i][1]))
3567                                        SimpleConstraintsListWave[CoefIndex][0] = "K"+num2istr(CoefIndex)
3568                                        SimpleConstraintsListWave[CoefIndex][1] = CoefListWave[i][1]
3569                                        SimpleConstraintsListWave[CoefIndex][3] = "< K"+num2istr(CoefIndex)+" <"
3570                                        CoefIndex += 1
3571                                endif
3572                        endfor
3573                        Make/O/N=(TotalParams,5) SimpleConstraintsSelectionWave
3574                        SimpleConstraintsSelectionWave[][0] = 0         // K labels
3575                        SimpleConstraintsSelectionWave[][1] = 0         // coefficient labels
3576                        SimpleConstraintsSelectionWave[][2] = 2         // editable- greater than constraints
3577                        SimpleConstraintsSelectionWave[][3] = 0         // "< Kn <"
3578                        SimpleConstraintsSelectionWave[][4] = 2         // editable- less than constraints
3579                        SetDimLabel 1, 0, 'Kn', SimpleConstraintsListWave
3580                        SetDimLabel 1, 1, 'Actual Coefficient', SimpleConstraintsListWave
3581                        SetDimLabel 1, 2, 'Min', SimpleConstraintsListWave
3582                        SetDimLabel 1, 3, ' ', SimpleConstraintsListWave
3583                        SetDimLabel 1, 4, 'Max', SimpleConstraintsListWave
3584                       
3585                        Wave/Z/T MoreConstraintsListWave
3586                        if (!WaveExists(MoreConstraintsListWave))
3587                                Make/N=(1,1)/T/O  MoreConstraintsListWave=""
3588                                Make/N=(1,1)/O MoreConstraintsSelectionWave=6
3589                                SetDimLabel 1,0,'Enter Constraint Expressions', MoreConstraintsListWave
3590                        endif
3591                        MoreConstraintsSelectionWave=6
3592                       
3593                        SetDatafolder $saveDF
3594                       
3595                        if (WinType("NewGF_GlobalFitConstraintPanel") > 0)
3596                                DoWindow/F NewGF_GlobalFitConstraintPanel
3597                        else
3598                                fNewGF_GlobalFitConstraintPanel()
3599                        endif
3600                endif
3601        endif
3602End
3603
3604static Function fNewGF_GlobalFitConstraintPanel()
3605
3606        NewPanel /W=(45,203,451,568)
3607        DoWindow/C NewGF_GlobalFitConstraintPanel
3608        AutoPositionWindow/M=0/E/R=NewGlobalFitPanel NewGF_GlobalFitConstraintPanel
3609
3610        GroupBox SimpleConstraintsGroup,pos={5,7},size={394,184},title="Simple Constraints"
3611        Button SimpleConstraintsClearB,pos={21,24},size={138,20},proc=WM_NewGlobalFit1#SimpleConstraintsClearBProc,title="Clear List"
3612        ListBox constraintsList,pos={12,49},size={380,127},listwave=root:Packages:NewGlobalFit:SimpleConstraintsListWave
3613        ListBox constraintsList,selWave=root:Packages:NewGlobalFit:SimpleConstraintsSelectionWave, mode=7
3614        ListBox constraintsList,widths={30,189,50,40,50}, editStyle= 1,frame=2,userColumnResize=1
3615
3616        GroupBox AdditionalConstraintsGroup,pos={5,192},size={394,138},title="Additional Constraints"
3617        ListBox moreConstraintsList,pos={12,239},size={380,85}, listwave=root:Packages:NewGlobalFit:MoreConstraintsListWave
3618        ListBox moreConstraintsList,selWave=root:Packages:NewGlobalFit:MoreConstraintsSelectionWave, mode=4
3619        ListBox moreConstraintsList, editStyle= 1,frame=2,userColumnResize=1
3620        Button NewConstraintLineButton,pos={21,211},size={138,20},title="Add a Line", proc=WM_NewGlobalFit1#NewGF_NewCnstrntLineButtonProc
3621        Button RemoveConstraintLineButton01,pos={185,211},size={138,20},title="Remove Selection", proc=WM_NewGlobalFit1#RemoveConstraintLineButtonProc
3622
3623        Button GlobalFitConstraintsDoneB,pos={6,339},size={50,20},proc=WM_NewGlobalFit1#GlobalFitConstraintsDoneBProc,title="Done"
3624EndMacro
3625
3626static Function SimpleConstraintsClearBProc(ctrlName) : ButtonControl
3627        String ctrlName
3628
3629        Wave/Z/T SimpleConstraintsListWave = root:Packages:NewGlobalFit:SimpleConstraintsListWave
3630        SimpleConstraintsListWave[][2] = ""
3631        SimpleConstraintsListWave[][4] = ""
3632End
3633
3634static Function NewGF_NewCnstrntLineButtonProc(ctrlName) : ButtonControl
3635        String ctrlName
3636
3637        Wave/Z/T MoreConstraintsListWave = root:Packages:NewGlobalFit:MoreConstraintsListWave
3638        Wave/Z MoreConstraintsSelectionWave = root:Packages:NewGlobalFit:MoreConstraintsSelectionWave
3639        Variable nRows = DimSize(MoreConstraintsListWave, 0)
3640        InsertPoints nRows, 1, MoreConstraintsListWave, MoreConstraintsSelectionWave
3641        MoreConstraintsListWave[nRows] = ""
3642        MoreConstraintsSelectionWave[nRows] = 6
3643        Redimension/N=(nRows+1,1) MoreConstraintsListWave, MoreConstraintsSelectionWave
3644End
3645
3646static Function RemoveConstraintLineButtonProc(ctrlName) : ButtonControl
3647        String ctrlName
3648
3649        Wave/Z/T MoreConstraintsListWave = root:Packages:NewGlobalFit:MoreConstraintsListWave
3650        Wave/Z MoreConstraintsSelectionWave = root:Packages:NewGlobalFit:MoreConstraintsSelectionWave
3651        Variable nRows = DimSize(MoreConstraintsListWave, 0)
3652        Variable i = 0
3653        do
3654                if (MoreConstraintsSelectionWave[i] & 1)
3655                        if (nRows == 1)
3656                                MoreConstraintsListWave[0] = ""
3657                                MoreConstraintsSelectionWave[0] = 6
3658                        else
3659                                DeletePoints i, 1, MoreConstraintsListWave, MoreConstraintsSelectionWave
3660                                nRows -= 1
3661                        endif
3662                else
3663                        i += 1
3664                endif
3665        while (i < nRows)
3666        Redimension/N=(nRows,1) MoreConstraintsListWave, MoreConstraintsSelectionWave
3667End
3668
3669
3670static Function GlobalFitConstraintsDoneBProc(ctrlName) : ButtonControl
3671        String ctrlName
3672
3673        DoWindow/K NewGF_GlobalFitConstraintPanel
3674End
3675
3676static Function NewGF_MakeConstraintWave()
3677
3678        Wave/Z/T SimpleConstraintsListWave = root:Packages:NewGlobalFit:SimpleConstraintsListWave
3679        Wave/Z/T MoreConstraintsListWave = root:Packages:NewGlobalFit:MoreConstraintsListWave
3680       
3681        Make/O/T/N=0 root:Packages:NewGlobalFit:GFUI_GlobalFitConstraintWave
3682        Wave/T GlobalFitConstraintWave = root:Packages:NewGlobalFit:GFUI_GlobalFitConstraintWave
3683        Variable nextRow = 0
3684        String constraintExpression
3685        Variable i, nPnts=DimSize(SimpleConstraintsListWave, 0)
3686        for (i=0; i < nPnts; i += 1)
3687                if (strlen(SimpleConstraintsListWave[i][2]) > 0)
3688                        InsertPoints nextRow, 1, GlobalFitConstraintWave
3689                        sprintf constraintExpression, "K%d > %s", i, SimpleConstraintsListWave[i][2]
3690                        GlobalFitConstraintWave[nextRow] = constraintExpression
3691                        nextRow += 1
3692                endif
3693                if (strlen(SimpleConstraintsListWave[i][4]) > 0)
3694                        InsertPoints nextRow, 1, GlobalFitConstraintWave
3695                        sprintf constraintExpression, "K%d < %s", i, SimpleConstraintsListWave[i][4]
3696                        GlobalFitConstraintWave[nextRow] = constraintExpression
3697                        nextRow += 1
3698                endif
3699        endfor
3700       
3701        nPnts = DimSize(MoreConstraintsListWave, 0)
3702        for (i = 0; i < nPnts; i += 1)
3703                if (strlen(MoreConstraintsListWave[i]) > 0)
3704                        InsertPoints nextRow, 1, GlobalFitConstraintWave
3705                        GlobalFitConstraintWave[nextRow] = MoreConstraintsListWave[i]
3706                        nextRow += 1
3707                endif
3708        endfor
3709end
3710
3711//***********************************
3712//
3713// Weighting
3714//
3715//***********************************
3716
3717static Function NewGF_WeightingCheckProc(ctrlName,checked) : CheckBoxControl
3718        String ctrlName
3719        Variable checked
3720       
3721        if (checked)
3722                Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3723                Variable numSets = DimSize(ListWave, 0)
3724
3725                if (NumSets == 0)
3726                        CheckBox NewGF_WeightingCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea, value=0
3727                        DoAlert 0, "You cannot choose weighting waves until you have selected data sets."
3728                        return 0
3729                else
3730                        String saveDF = GetDatafolder(1)
3731                        SetDatafolder root:Packages:NewGlobalFit
3732                       
3733                        Wave/T/Z WeightingListWave
3734                        if (!(WaveExists(WeightingListWave) && (DimSize(WeightingListWave, 0) == NumSets)))
3735                                Make/O/N=(NumSets, 2)/T WeightingListWave=""
3736                        endif
3737                        WeightingListWave[][0] = ListWave[p][0][1]
3738                        Make/O/N=(NumSets, 2) WeightingSelectionWave
3739                        WeightingSelectionWave[][0] = 0         // Data Sets
3740                        WeightingSelectionWave[][1] = 0         // Weighting Waves; not editable- select from menu
3741                        SetDimLabel 1, 0, 'Data Set', WeightingListWave
3742                        SetDimLabel 1, 1, 'Weight Wave', WeightingListWave
3743                       
3744                        SetDatafolder $saveDF
3745                       
3746                        if (WinType("NewGF_WeightingPanel") > 0)
3747                                DoWindow/F NewGF_WeightingPanel
3748                        else
3749                                fNewGF_WeightingPanel()
3750                        endif
3751                       
3752//                      Variable/G root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD = NumVarOrDefault("root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD", 1)
3753                        Variable/G root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD = 1                //SRK force StdDev radio button
3754                        NVAR GlobalFit_WeightsAreSD = root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD
3755                        if (GlobalFit_WeightsAreSD)
3756                                WeightsSDRadioProc("WeightsSDRadio",1)
3757                        else
3758                                WeightsSDRadioProc("WeightsInvSDRadio",1)
3759                        endif
3760                                               
3761                endif
3762        endif   
3763end
3764
3765static Function fNewGF_WeightingPanel() : Panel
3766
3767        NewPanel /W=(339,193,745,408)
3768        DoWindow/C NewGF_WeightingPanel
3769        AutoPositionWindow/M=0/E/R=NewGlobalFitPanel NewGF_WeightingPanel
3770       
3771        ListBox WeightWaveListBox,pos={9,63},size={387,112}, mode=10, listWave = root:Packages:NewGlobalFit:WeightingListWave,userColumnResize=1
3772        ListBox WeightWaveListBox, selWave = root:Packages:NewGlobalFit:WeightingSelectionWave, frame=2,proc=WM_NewGlobalFit1#NewGF_WeightListProc
3773
3774        Button GlobalFitWeightDoneButton,pos={24,186},size={50,20},proc=WM_NewGlobalFit1#GlobalFitWeightDoneButtonProc,title="Done"
3775        Button GlobalFitWeightCancelButton,pos={331,186},size={50,20},proc=WM_NewGlobalFit1#GlobalFitWeightCancelButtonProc,title="Cancel"
3776
3777//SRK - disable - simply click on the row to set, based on name structure
3778        PopupMenu GlobalFitWeightWaveMenu,pos={9,5},size={152,20},title="Select Weight Wave"
3779        PopupMenu GlobalFitWeightWaveMenu,mode=0,value= #"WM_NewGlobalFit1#ListPossibleWeightWaves()", proc=WM_NewGlobalFit1#WeightWaveSelectionMenu
3780        PopupMenu GlobalFitWeightWaveMenu,disable=2
3781//eSRK
3782
3783//      Button WeightClearSelectionButton,pos={276,5},size={120,20},proc=WM_NewGlobalFit1#WeightClearSelectionButtonProc,title="Clear Selection"
3784//      Button WeightClearAllButton,pos={276,32},size={120,20},proc=WM_NewGlobalFit1#WeightClearSelectionButtonProc,title="Clear All"
3785
3786        GroupBox WeightStdDevRadioGroup,pos={174,4},size={95,54},title="Weights  are"
3787
3788        CheckBox WeightsSDRadio,pos={185,22},size={60,14},proc=WM_NewGlobalFit1#WeightsSDRadioProc,title="Std. Dev."
3789        CheckBox WeightsSDRadio,value= 1, mode=1
3790        CheckBox WeightsInvSDRadio,pos={185,38},size={73,14},proc=WM_NewGlobalFit1#WeightsSDRadioProc,title="1/Std. Dev."
3791        CheckBox WeightsInvSDRadio,value= 0, mode=1
3792EndMacro
3793
3794static Function NewGF_WeightListProc(ctrlName,row,col,event) : ListBoxControl
3795        String ctrlName     // name of this control
3796        Variable row        // row if click in interior, -1 if click in title
3797        Variable col        // column number
3798        Variable event      // event code
3799       
3800        if (event == 1)
3801                Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3802                Variable NumSets = DimSize(WeightingListWave, 0)
3803                if ( (row == -1) && (col == 1) )
3804                        Wave WeightingSelWave = root:Packages:NewGlobalFit:WeightingSelectionWave
3805                        WeightingSelWave[][1] = 1
3806                elseif ( (col == 1) && (row >= 0) && (row < NumSets) )
3807                        if (GetKeyState(0) == 0)
3808                                Wave/Z w = $(WeightingListWave[row][0])
3809                                if (WaveExists(w))
3810                                        //SRK - since I enforce the loading and naming, bypass the selection
3811                                        //String RowsText = num2str(DimSize(w, 0))
3812                                        //PopupContextualMenu "_calculated_;"+WaveList("*",";","MINROWS:"+RowsText+",MAXROWS:"+RowsText+",DIMS:1,CMPLX:0,TEXT:0,BYTE:0,WORD:0,INTEGER:0")
3813                                       
3814                                        //if (V_flag > 0)
3815                                        //      Wave/Z w = $S_selection
3816                                        //      if (WaveExists(w))
3817                                        //              WeightingListWave[row][1] = GetWavesDataFolder(w, 2)
3818                                        //      endif
3819                                        //endif
3820                                        String yStr = WeightingListWave[row][0]
3821                                        yStr = RemoveEnding(yStr , "i")
3822                                        WeightingListWave[row][1] = yStr + "s"
3823                                        //eSRK
3824                                endif
3825                        endif
3826                endif
3827        endif
3828end
3829
3830static Function GlobalFitWeightDoneButtonProc(ctrlName) : ButtonControl
3831        String ctrlName
3832
3833        Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3834        Variable NumSets = DimSize(WeightingListWave, 0)
3835       
3836        Variable i
3837        for (i = 0; i < NumSets; i += 1)
3838                Wave/Z w = $(WeightingListWave[i][1])
3839                if (!WaveExists(w))
3840                        ListBox WeightWaveListBox, win=NewGF_WeightingPanel, selRow = i
3841                        DoAlert 0, "The wave \""+WeightingListWave[i][1]+"\" does not exist."
3842                        WeightingListWave[i][1] = ""
3843                        return -1
3844                endif
3845        endfor
3846               
3847        DoWindow/K NewGF_WeightingPanel
3848End
3849
3850static Function GlobalFitWeightCancelButtonProc(ctrlName) : ButtonControl
3851        String ctrlName
3852
3853        DoWindow/K NewGF_WeightingPanel
3854        CheckBox NewGF_WeightingCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea, value=0
3855End
3856
3857static Function/S ListPossibleWeightWaves()
3858
3859        Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3860        Wave/Z WeightingSelectionWave=root:Packages:NewGlobalFit:WeightingSelectionWave
3861
3862        String DataSetName=""
3863        Variable i
3864       
3865        ControlInfo/W=NewGF_WeightingPanel WeightWaveListBox
3866        DataSetName = WeightingListWave[V_value][0]
3867       
3868        if (strlen(DataSetName) == 0)
3869                return "No Selection;"
3870        endif
3871       
3872        Wave/Z ds = $DataSetName
3873        if (!WaveExists(ds))
3874                return "Bad Data Set:"+DataSetName+";"
3875        endif
3876       
3877        Variable numpoints = DimSize(ds, 0)
3878        String theList = ""
3879        i=0
3880        do
3881                Wave/Z w = WaveRefIndexed("", i, 4)
3882                if (!WaveExists(w))
3883                        break
3884                endif
3885                if ( (DimSize(w, 0) == numpoints) && (WaveType(w) & 6) )                // select floating-point waves with the right number of points
3886                        theList += NameOfWave(w)+";"
3887                endif
3888                i += 1
3889        while (1)
3890       
3891        if (i == 0)
3892                return "None Available;"
3893        endif
3894       
3895        return theList
3896end
3897
3898static Function WeightWaveSelectionMenu(ctrlName,popNum,popStr) : PopupMenuControl
3899        String ctrlName
3900        Variable popNum
3901        String popStr
3902
3903        Wave/Z w = $popStr
3904        if (WaveExists(w))
3905                Wave/T WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3906                Wave WeightingSelWave = root:Packages:NewGlobalFit:WeightingSelectionWave
3907                Variable nrows = DimSize(WeightingListWave, 0)
3908                Variable i
3909                for (i = 0; i < nrows; i += 1)
3910                        if ( (WeightingSelWave[i][0] & 1) || (WeightingSelWave[i][1]) )
3911                                WeightingListWave[i][1] = GetWavesDatafolder(w, 2)
3912                        endif
3913                endfor
3914        endif
3915end
3916
3917//static Function WeightClearSelectionButtonProc(ctrlName) : ButtonControl
3918//      String ctrlName
3919//
3920//      Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3921//      StrSwitch (ctrlName)
3922//              case "WeightClearSelectionButton":
3923//                      Wave WeightingSelWave = root:Packages:NewGlobalFit:WeightingSelectionWave
3924//                      Variable nrows = DimSize(WeightingListWave, 0)
3925//                      Variable i
3926//                      for (i = 0; i < nrows; i += 1)
3927//                              if ( (WeightingSelWave[i][0] & 1) || (WeightingSelWave[i][1]) )
3928//                                      WeightingListWave[i][1] = ""
3929//                              endif
3930//                      endfor
3931//                      break;
3932//              case "WeightClearAllButton":
3933//                      WeightingListWave[][1] = ""
3934//                      break;
3935//      endswitch
3936//End
3937
3938static Function WeightsSDRadioProc(name,value)
3939        String name
3940        Variable value
3941       
3942        NVAR GlobalFit_WeightsAreSD= root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD
3943       
3944        strswitch (name)
3945                case "WeightsSDRadio":
3946                        GlobalFit_WeightsAreSD = 1
3947                        break
3948                case "WeightsInvSDRadio":
3949                        GlobalFit_WeightsAreSD = 0
3950                        break
3951        endswitch
3952        CheckBox WeightsSDRadio, win=NewGF_WeightingPanel, value= GlobalFit_WeightsAreSD==1
3953        CheckBox WeightsInvSDRadio, win=NewGF_WeightingPanel, value= GlobalFit_WeightsAreSD==0
3954End
3955
3956// This function is strictly for the use of the Global Analysis control panel. It assumes that the DataSets
3957// wave so far has just two columns, the Y and X wave columns
3958static Function GFUI_AddWeightWavesToDataSets(DataSets)
3959        Wave/T DataSets
3960       
3961        Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3962       
3963        Redimension/N=(-1, 3) DataSets
3964        SetDimLabel 1, 2, Weights, DataSets
3965       
3966        Variable numSets = DimSize(DataSets, 0)
3967        Variable i
3968        for (i = 0; i < NumSets; i += 1)
3969                Wave/Z w = $(WeightingListWave[i][1])
3970                if (WaveExists(w))
3971                        wave/Z yw = $(DataSets[i][0])
3972                        if (WaveExists(yw) && (numpnts(w) != numpnts(yw)))
3973                                DoAlert 0,"The weighting wave \""+WeightingListWave[i][1]+"\" has a different number points than Y wave \""+(DataSets[i][0])+"\""
3974                                return -1
3975                        endif
3976                        DataSets[i][2] = WeightingListWave[i][1]
3977                else
3978                        Redimension/N=(-1,2) DataSets
3979                        DoAlert 0,"The weighting wave \""+WeightingListWave[i][1]+"\" for Y wave \""+(DataSets[i][0])+"\" does not exist."
3980                        return -1
3981                endif
3982        endfor
3983       
3984        return 0
3985end
3986
3987static Function GFUI_AddMaskWavesToDataSets(DataSets)
3988        Wave/T DataSets
3989       
3990        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
3991       
3992        Variable startingNCols = DimSize(DataSets, 1)
3993        Redimension/N=(-1, startingNCols+1) DataSets
3994        SetDimLabel 1, startingNCols, Masks, DataSets
3995       
3996        Variable numSets = DimSize(DataSets, 0)
3997        Variable i
3998        for (i = 0; i < NumSets; i += 1)
3999                Wave/Z w = $(MaskingListWave[i][1])
4000                if (WaveExists(w))
4001                        wave/Z yw = $(DataSets[i][0])
4002                        if (WaveExists(yw) && (numpnts(w) != numpnts(yw)))
4003                                DoAlert 0,"The mask wave \""+MaskingListWave[i][1]+"\" has a different number points than Y wave \""+(DataSets[i][0])+"\""
4004                                return -1
4005                        endif
4006                        DataSets[i][startingNCols] = MaskingListWave[i][1]
4007                else
4008                        Redimension/N=(-1,startingNCols) DataSets
4009                        DoAlert 0,"The mask wave \""+MaskingListWave[i][1]+"\" for Y wave \""+(DataSets[i][0])+"\" does not exist."
4010                        return -1
4011                endif
4012        endfor
4013       
4014        return 0
4015end
4016
4017
4018static Function NewGF_CovMatrixCheckProc(ctrlName,checked) : CheckBoxControl
4019        String ctrlName
4020        Variable checked
4021
4022        if (!checked)
4023                Checkbox NewGF_CorrelationMatrixCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=0
4024        endif
4025End
4026
4027static Function NewGF_CorMatrixCheckProc(ctrlName,checked) : CheckBoxControl
4028        String ctrlName
4029        Variable checked
4030
4031        if (checked)
4032                Checkbox NewGF_DoCovarMatrix, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=1
4033        endif
4034End
4035
4036
4037static Function NewGF_FitCurvesCheckProc(ctrlName,checked) : CheckBoxControl
4038        String ctrlName
4039        Variable checked
4040
4041        if (!checked)
4042                Checkbox NewGF_AppendResultsCheckbox, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=0
4043                Checkbox NewGF_DoResidualCheck, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=0
4044        endif
4045End
4046
4047static Function NewGF_AppendResultsCheckProc(ctrlName,checked) : CheckBoxControl
4048        String ctrlName
4049        Variable checked
4050
4051        if (checked)
4052                Checkbox NewGF_MakeFitCurvesCheck, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=1
4053        endif
4054End
4055
4056static Function NewGF_CalcResidualsCheckProc(ctrlName,checked) : CheckBoxControl
4057        String ctrlName
4058        Variable checked
4059
4060        if (checked)
4061                Checkbox NewGF_MakeFitCurvesCheck, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=1
4062        endif
4063End
4064
4065
4066//***********************************
4067//
4068// Data masking
4069//
4070//***********************************
4071
4072static Function NewGF_MaskingCheckProc(ctrlName,checked) : CheckBoxControl
4073        String ctrlName
4074        Variable checked
4075       
4076        if (checked)
4077                Wave/T DataSetList = root:Packages:NewGlobalFit:NewGF_DataSetListWave
4078                Variable numSets = DimSize(DataSetList, 0)
4079
4080                if (NumSets == 0)
4081                        CheckBox NewGF_MaskingCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea, value=0
4082                        DoAlert 0, "You cannot add Masking waves until you have selected data sets."
4083                        return 0
4084                else
4085                        String saveDF = GetDatafolder(1)
4086                        SetDatafolder root:Packages:NewGlobalFit
4087                       
4088                        Wave/T/Z MaskingListWave
4089                        if (!(WaveExists(MaskingListWave) && (DimSize(MaskingListWave, 0) == NumSets)))
4090                                Make/O/N=(NumSets, 2)/T MaskingListWave=""
4091                        endif
4092                        MaskingListWave[][0] = DataSetList[p][0][1]
4093                        Make/O/N=(NumSets, 2) MaskingSelectionWave
4094                        MaskingSelectionWave[][0] = 0           // Data Sets
4095                        MaskingSelectionWave[][1] = 0           // Masking Waves; not editable- select from menu
4096                        SetDimLabel 1, 0, 'Data Set', MaskingListWave
4097                        SetDimLabel 1, 1, 'Mask Wave', MaskingListWave
4098                       
4099                        SetDatafolder $saveDF
4100                       
4101                        if (WinType("NewGF_GlobalFitMaskingPanel") > 0)
4102                                DoWindow/F NewGF_GlobalFitMaskingPanel
4103                        else
4104                                fNewGF_GlobalFitMaskingPanel()
4105                        endif
4106                endif
4107        //SRK - hide unused cursors
4108        else
4109                //not checked, remove cursors
4110                Cursor/K A
4111                Cursor/K B
4112                HideInfo
4113        //eSRK
4114        endif   
4115end
4116
4117static Function fNewGF_GlobalFitMaskingPanel() : Panel
4118
4119        NewPanel /W=(339,193,745,408)
4120        DoWindow/C NewGF_GlobalFitMaskingPanel
4121        AutoPositionWindow/M=0/E/R=NewGlobalFitPanel NewGF_GlobalFitMaskingPanel
4122       
4123        ListBox MaskWaveListBox,pos={9,63},size={387,112}, mode=10, listWave = root:Packages:NewGlobalFit:MaskingListWave,userColumnResize=1
4124        //SRK - use my own selection procedure, not the contextual menu in the ListBox
4125//      ListBox MaskWaveListBox, selWave = root:Packages:NewGlobalFit:MaskingSelectionWave, frame=2, proc=WM_NewGlobalFit1#NewGF_MaskListProc
4126        ListBox MaskWaveListBox, selWave = root:Packages:NewGlobalFit:MaskingSelectionWave, frame=2
4127        //eSRK
4128        Button GlobalFitMaskDoneButton,pos={24,186},size={50,20},proc=WM_NewGlobalFit1#GlobalFitMaskDoneButtonProc,title="Done"
4129        Button GlobalFitMaskCancelButton,pos={331,186},size={50,20},proc=WM_NewGlobalFit1#GlobalFitMaskCancelButtonProc,title="Cancel"
4130        PopupMenu GlobalFitMaskWaveMenu,pos={9,5},size={152,20},title="Select Mask Wave"
4131        PopupMenu GlobalFitMaskWaveMenu,mode=0,value= #"WM_NewGlobalFit1#ListPossibleMaskWaves()", proc=WM_NewGlobalFit1#MaskWaveSelectionMenu
4132        Button MaskClearSelectionButton,pos={276,5},size={120,20},proc=WM_NewGlobalFit1#MaskClearSelectionButtonProc,title="Clear Selection"
4133        Button MaskClearAllButton,pos={276,32},size={120,20},proc=WM_NewGlobalFit1#MaskClearSelectionButtonProc,title="Clear All"
4134       
4135        //SRK
4136        Button MaskFromCursorsButton,pos={130,32},size={135,20},proc=MaskFromCursorsButtonProc,title="Mask From Cursors"
4137        ListBox MaskWaveListBox,proc=MaskListBoxSelectionProc
4138        Button MaskShowInfoButton,pos={9,32},size={110,20},proc=MaskShowInfoButtonProc,title="Show Cursors"
4139        //eSRK
4140EndMacro
4141
4142//SRK
4143// make a temporary masking wave from the selected data set
4144// and the cursor positions
4145//
4146Function MaskFromCursorsButtonProc(ctrlName) : ButtonControl
4147        String ctrlName
4148
4149        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4150        Wave selWave = root:Packages:NewGlobalFit:MaskingSelectionWave
4151       
4152        Variable numRow=DimSize(selWave, 0),ii=0
4153        String DataSetName=""
4154        do
4155                if(selWave[ii][0] || selWave[ii][1])
4156                        break
4157                endif
4158                ii+=1
4159        while(ii<numRow)
4160        numRow=ii
4161       
4162        DataSetName = MaskingListWave[numRow][0]                //"root:yTraceName"
4163        Wave w = $DataSetName
4164       
4165        Duplicate/O $DataSetName,$(DataSetName+"mask")  //mask is in root: folder
4166       
4167        MaskingListWave[numRow][1] = DataSetName+"mask"
4168       
4169        Wave mm = $(DataSetName+"mask")
4170        mm=1            //mask nothing as the default
4171       
4172        //set the masking based on the cursors
4173        Make/O/N=2 csrPts
4174        csrPts[0] = xcsr(A)
4175        csrPts[1] = xcsr(B)
4176        Sort csrPts,csrPts              //pt[0] is smaller - guaranteed
4177       
4178        if(csrPts[0] > 0)
4179                mm[0,csrPts[0]-1] = 0
4180        endif
4181        if(csrPts[1] < (numpnts(mm)-1) )
4182                mm[csrPts[1]+1,numpnts(mm)-1] = 0
4183        endif
4184       
4185        Killwaves/Z csrPts     
4186End
4187
4188//SRK
4189Function MaskShowInfoButtonProc(ctrlName) : ButtonControl
4190        String ctrlName
4191        ShowInfo                //topmost graph
4192        return(0)
4193End
4194
4195//SRK
4196// based on the selected data set in the list box, put cursors
4197// on the proper data set, and put them at the right points
4198// if the masking wave exists
4199//
4200Function MaskListBoxSelectionProc(ctrlName,row,col,event)       // : ListboxControl
4201        String ctrlName     // name of this control
4202        Variable row        // row if click in interior, -1 if click in title
4203        Variable col        // column number
4204        Variable event      // event code
4205       
4206        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4207       
4208        String str=MaskingListWave[row][0]              //"root:yTraceName"
4209        Variable ptA=0,ptB=numpnts($(str[5,strlen(str)-1]))-1           //default to end points
4210        WAVE/Z mm = $(str+"mask")
4211        if(waveexists(mm))
4212                FindLevel/P/Q mm,1
4213                ptA = V_LevelX
4214                FindLevel/P/Q/R=[ptA] mm,0
4215                if(V_flag==0)
4216                        ptB = V_LevelX-1                //level was found, use it. otherwise use default
4217                endif
4218        endif
4219        // get the right target window, hopefully the top graph
4220        String tmp= StringFromList(0,WinList("*", ";","WIN:1"),";")             //first graph is "topmost"
4221        Cursor/P/W=$tmp A, $(ParseFilePath(0, str, ":", 1, 0)),ptA                      //just give me the wave name, not the full path
4222        Cursor/P/W=$tmp B, $(ParseFilePath(0, str, ":", 1, 0)),ptB
4223       
4224        return 0            // other return values reserved
4225End
4226
4227static Function NewGF_MaskListProc(ctrlName,row,col,event) : ListBoxControl
4228        String ctrlName     // name of this control
4229        Variable row        // row if click in interior, -1 if click in title
4230        Variable col        // column number
4231        Variable event      // event code
4232       
4233        if (event == 1)
4234                Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4235                Variable numSets = DimSize(MaskingListWave, 0)
4236                if ( (row == -1) && (col == 1) )
4237                        Wave MaskingSelWave = root:Packages:NewGlobalFit:MaskingSelectionWave
4238                        MaskingSelWave[][1] = 1
4239                elseif ( (col == 1) && (row >= 0) && (row < NumSets) )
4240                        if (GetKeyState(0) == 0)
4241                                Wave/Z w = $(MaskingListWave[row][0])
4242                                if (WaveExists(w))
4243                                        String RowsText = num2str(DimSize(w, 0))
4244                                        PopupContextualMenu "_calculated_;"+WaveList("*",";","MINROWS:"+RowsText+",MAXROWS:"+RowsText+",DIMS:1,CMPLX:0,TEXT:0,BYTE:0,WORD:0,INTEGER:0")
4245                                        if (V_flag > 0)
4246                                                Wave/Z w = $S_selection
4247                                                if (WaveExists(w))
4248                                                        MaskingListWave[row][1] = GetWavesDataFolder(w, 2)
4249                                                endif
4250                                        endif
4251                                endif
4252                        endif
4253                endif
4254        endif
4255end
4256
4257static Function GlobalFitMaskDoneButtonProc(ctrlName) : ButtonControl
4258        String ctrlName
4259
4260        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4261        Variable numSets = DimSize(MaskingListWave, 0)
4262
4263        Variable i
4264        for (i = 0; i < NumSets; i += 1)
4265                Wave/Z w = $(MaskingListWave[i][1])
4266                if (!WaveExists(w))
4267                        if (strlen(MaskingListWave[i][1]) != 0)
4268                                ListBox MaskWaveListBox, win=NewGF_GlobalFitMaskingPanel, selRow = i
4269                                DoAlert 0, "The wave \""+MaskingListWave[i][1]+"\" does not exist."
4270                                MaskingListWave[i][1] = ""
4271                                return -1
4272                        endif
4273                endif
4274        endfor
4275               
4276        DoWindow/K NewGF_GlobalFitMaskingPanel
4277End
4278
4279static Function GlobalFitMaskCancelButtonProc(ctrlName) : ButtonControl
4280        String ctrlName
4281
4282        DoWindow/K NewGF_GlobalFitMaskingPanel
4283        CheckBox NewGF_MaskingCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea, value=0
4284End
4285
4286static Function/S ListPossibleMaskWaves()
4287
4288        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4289        Wave/Z MaskingSelectionWave=root:Packages:NewGlobalFit:MaskingSelectionWave
4290        Variable NumSets= DimSize(MaskingListWave, 0)
4291
4292        String DataSetName=""
4293        Variable i
4294       
4295        ControlInfo/W=NewGF_GlobalFitMaskingPanel MaskWaveListBox
4296        DataSetName = MaskingListWave[V_value][0]
4297       
4298        if (strlen(DataSetName) == 0)
4299                return "No Selection;"
4300        endif
4301       
4302        Wave/Z ds = $DataSetName
4303        if (!WaveExists(ds))
4304                return "Unknown Data Set;"
4305        endif
4306       
4307        Variable numpoints = DimSize(ds, 0)
4308        String theList = ""
4309        i=0
4310        do
4311                Wave/Z w = WaveRefIndexed("", i, 4)
4312                if (!WaveExists(w))
4313                        break
4314                endif
4315                if ( (DimSize(w, 0) == numpoints) && (WaveType(w) & 6) )                // select floating-point waves with the right number of points
4316                        theList += NameOfWave(w)+";"
4317                endif
4318                i += 1
4319        while (1)
4320       
4321        if (i == 0)
4322                return "None Available;"
4323        endif
4324       
4325        return theList
4326end
4327
4328static Function MaskWaveSelectionMenu(ctrlName,popNum,popStr) : PopupMenuControl
4329        String ctrlName
4330        Variable popNum
4331        String popStr
4332
4333        Wave/Z w = $popStr
4334        if (WaveExists(w))
4335                Wave/T MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4336                Wave MaskingSelWave = root:Packages:NewGlobalFit:MaskingSelectionWave
4337                Variable nrows = DimSize(MaskingListWave, 0)
4338                Variable i
4339                for (i = 0; i < nrows; i += 1)
4340                        if ( (MaskingSelWave[i][0] & 1) || (MaskingSelWave[i][1]) )
4341                                MaskingListWave[i][1] = GetWavesDatafolder(w, 2)
4342                        endif
4343                endfor
4344        endif
4345end
4346
4347static Function MaskClearSelectionButtonProc(ctrlName) : ButtonControl
4348        String ctrlName
4349
4350        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4351        StrSwitch (ctrlName)
4352                case "MaskClearSelectionButton":
4353                        Wave MaskingSelWave = root:Packages:NewGlobalFit:MaskingSelectionWave
4354                        Variable nrows = DimSize(MaskingListWave, 0)
4355                        Variable i
4356                        for (i = 0; i < nrows; i += 1)
4357                                if ( (MaskingSelWave[i][0] & 1) || (MaskingSelWave[i][1]) )
4358                                        MaskingListWave[i][1] = ""
4359                                endif
4360                        endfor
4361                        break;
4362                case "MaskClearAllButton":
4363                        MaskingListWave[][1] = ""
4364                        break;
4365        endswitch
4366End
4367
4368
4369
4370//***********************************
4371//
4372// Load/Save initial guesses from/to a wave
4373//
4374//***********************************
4375
4376Function/S NewGF_ListInitGuessWaves(SelectedOnly, LinkRowsOK)
4377        Variable SelectedOnly
4378        Variable LinkRowsOK
4379
4380        Variable numrows
4381//      ControlInfo/W=NewGlobalFitPanel#Tab1ContentPanel NewGF_InitGuessCopySelCheck
4382        if (SelectedOnly)
4383                numrows = totalSelRealCoefsFromCoefList(LinkRowsOK)
4384        else
4385                numrows = totalRealCoefsFromCoefList(LinkRowsOK)
4386        endif
4387       
4388        String numrowsstr = num2str(numrows)
4389        return WaveList("*", ";", "DIMS:1,MINROWS:"+numrowsstr+",MAXROWS:"+numrowsstr+",BYTE:0,INTEGER:0,WORD:0,CMPLX:0,TEXT:0")
4390end
4391
4392char ctrlName[MAX_OBJ_NAME+1]   Control name.
4393char win[MAX_WIN_PATH+1]        Host (sub)window.
4394STRUCT Rect winRect     Local coordinates of host window.
4395STRUCT Rect ctrlRect    Enclosing rectangle of the control.
4396STRUCT Point mouseLoc   Mouse location.
4397Int32 eventCode Event that caused the procedure to execute. Main event is mouse up=2.
4398String userdata Primary (unnamed) user data. If this changes, it is written back automatically.
4399Int32 popNum    Item number currently selected (1-based).
4400char popStr[MAXCMDLEN]  Contents of current popup item.
4401
4402Function NewGF_SetCoefsFromWaveProc(PU_Struct) : PopupMenuControl
4403        STRUCT WMPopupAction &PU_Struct
4404
4405        if (PU_Struct.eventCode == 2)                   // mouse up
4406                Wave w = $(PU_Struct.popStr)
4407                if (!WaveExists(w))
4408                        DoAlert 0, "The wave you selected does not exist for some reason."
4409                        return 0
4410                endif
4411               
4412                SetCoefListFromWave(w, 2, 0, 0)
4413        endif
4414end
4415
4416Function NewGF_SaveCoefsToWaveProc(PU_Struct) : PopupMenuControl
4417        STRUCT WMPopupAction &PU_Struct
4418
4419        if (PU_Struct.eventCode == 2)                   // mouse up
4420                if (CmpStr(PU_Struct.popStr, "New Wave...") == 0)
4421                        Variable numRowsNeeded = totalRealCoefsFromCoefList(0)
4422                        String newName = NewGF_GetNewWaveName()
4423                        if (strlen(newName) == 0)
4424                                return 0
4425                        endif
4426                        Make/O/N=(numRowsNeeded)/D $newName
4427                        Wave w = $newName
4428                else
4429                        Wave w = $(PU_Struct.popStr)
4430                endif
4431               
4432                SaveCoefListToWave(w, 2, 0, 0)
4433        endif
4434end
4435
4436Function/S NewGF_GetNewWaveName()
4437
4438        String newName
4439        Prompt newName, "Enter a name for the new wave:"
4440        DoPrompt "Get New Wave Name", newName
4441        if (V_flag)
4442                return ""
4443        endif
4444       
4445        return newName
4446end
4447       
4448//***********************************
4449//
4450// Utility functions
4451//
4452//***********************************
4453
4454// returns semicolon-separated list of items in a selected column of a 1D or 2D text wave
4455static Function/S TextWaveToList(twave, column)
4456        Wave/T twave
4457        Variable column
4458       
4459        String returnValue = ""
4460        Variable nRows = DimSize(twave, 0)
4461        Variable i
4462       
4463        for (i = 0; i < nRows; i += 1)
4464                returnValue += (twave[i][column])+";"
4465        endfor
4466       
4467        return returnValue
4468end
4469
4470static Function IsLinkText(theText)
4471        String theText
4472       
4473        return (CmpStr(theText[0,4], "LINK:") == 0)
4474end
4475
4476static Function ItemListedInWave(Item, theWave)
4477        String Item
4478        Wave/T theWave
4479       
4480        return ItemNumberInTextWaveList(Item, theWave) >= 0
4481end
4482
4483static Function ItemNumberInTextWaveList(Item, theWave)
4484        String Item
4485        Wave/T theWave
4486       
4487        Variable i
4488        Variable npnts = DimSize(theWave, 0)
4489        Variable itemNumber = -1
4490       
4491        for (i = 0; i < npnts; i += 1)
4492                if ( (strlen(theWave[i]) > 0) && (CmpStr(theWave[i], Item) == 0) )
4493                        itemNumber = i
4494                        break
4495                endif
4496        endfor
4497       
4498        return itemNumber
4499end
4500
4501// makes a 1D or 2D text wave with each item from a semicolon-separated list in the wave's rows
4502// in the selected column. You are free to fill other columns as you wish.
4503static Function ListToTwave(theList, twaveName, columns, column)
4504        String theList
4505        String twaveName
4506        Variable columns
4507        Variable column
4508       
4509        Variable nRows = ItemsInList(theList)
4510        Variable i
4511       
4512        Make/T/O/N=(nRows, columns) $twaveName
4513        Wave/T twave = $twaveName
4514       
4515        for (i = 0; i < nRows; i += 1)
4516                twave[i][column] = StringFromList(i, theList)
4517        endfor
4518end
4519
4520static Function totalCoefsFromCoefList()
4521
4522        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4523       
4524        return DimSize(CoefListWave, 0)
4525end
4526
4527static Function totalRealCoefsFromCoefList(LinkRowsOK)
4528        Variable LinkRowsOK
4529
4530        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4531
4532        Variable i
4533        Variable totalNonlinkRows = 0
4534        Variable numrows = DimSize(CoefListWave, 0)
4535        for (i = 0; i < numrows; i += 1)
4536                if (LinkRowsOK || !IsLinkText(CoefListWave[i][1]))
4537                        totalNonlinkRows += 1
4538                endif
4539        endfor
4540       
4541        return totalNonlinkRows
4542end
4543
4544static Function totalSelRealCoefsFromCoefList(LinkRowsOK)
4545        Variable LinkRowsOK
4546
4547        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4548        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
4549
4550        Variable i
4551        Variable totalNonlinkRows = 0
4552        Variable numrows = DimSize(CoefListWave, 0)
4553        for (i = 0; i < numrows; i += 1)
4554                if (LinkRowsOK || !IsLinkText(CoefListWave[i][1]))
4555                        if (IsRowSelected(CoefSelWave, i))
4556                                totalNonlinkRows += 1
4557                        endif
4558                endif
4559        endfor
4560       
4561        return totalNonlinkRows
4562end
4563
4564static Function SetCoefListFromWave(w, col, SetOnlySelectedCells, OKtoSetLinkRows)
4565        Wave w
4566        Variable col
4567        Variable SetOnlySelectedCells
4568        Variable OKtoSetLinkRows
4569       
4570        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4571        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
4572
4573        Variable coefIndex = 0;
4574        Variable i,j
4575        Variable nTotalCoefs = DimSize(CoefListWave, 0)
4576       
4577        String formatStr = "%.15g"
4578        if ( (WaveType(w) & 4) == 0)            // it's not a double-precision wave
4579                formatStr = "%.6g"
4580        endif
4581       
4582        for (i = 0; i < nTotalCoefs; i += 1)            // indent 1
4583//              if ( SetOnlySelectedCells && ((CoefSelWave[i][col] & 9) == 0) )
4584                if ( SetOnlySelectedCells && !IsRowSelected(CoefSelWave, i) )
4585                        continue
4586                endif
4587//              if (!OKtoSetLinkRows && !IsLinkText(CoefListWave[i][1]))
4588                if (!IsLinkText(CoefListWave[i][1]))            // indent 2
4589                        // first part sets the coefficient list wave text from the appropriate element in the input wave
4590               
4591                        if (col == 3)
4592                                if (w[coefIndex][0])
4593                                        CoefSelWave[i][col] = 0x20 + 0x10
4594                                else
4595                                        CoefSelWave[i][col] = 0x20
4596                                endif
4597                        else
4598                                string dumstr
4599                                sprintf dumstr, formatStr, w[coefIndex][0]
4600                                Variable nstr = strlen(dumstr)
4601                                for (j = 0; j < nstr; j += 1)
4602                                        if (char2num(dumstr[j]) != char2num(" "))
4603                                                break
4604                                        endif
4605                                endfor
4606                                if (j > 0)
4607                                        dumstr = dumstr[j, strlen(dumstr)-1]
4608                                endif
4609                                CoefListWave[i][col] = dumstr
4610                        endif
4611                else            // indent 2
4612                        string linktext
4613                        // We've hit a link cell (refers to an earlier row)
4614                        //
4615                        // If we are setting the entire wave, rather than setting the value in the row, we should instead copy the value
4616                        // from the row containing the master copy (the row to which the link refers). (first IF block)
4617                        //
4618                        // 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
4619                        // and any other rows that link to it.
4620                        if (!SetOnlySelectedCells)              // indent 3
4621                                // copy linked text from master row when we encounter a linked cell. The links should always be after the cell they link to.
4622                                linktext = (CoefListWave[i][1])[5,strlen(CoefListWave[i][1])-1]
4623                                for (j = 0; j < nTotalCoefs; j += 1)
4624                                        if (CmpStr(linktext, CoefListWave[j][1]) == 0)
4625                                                if (col == 3)
4626                                                        if (CoefSelWave[j][col] & 0x10)
4627                                                                CoefListWave[i][col] = " X"
4628                                                        else
4629                                                                CoefListWave[i][col] = ""
4630                                                        endif
4631                                                else
4632                                                        CoefListWave[i][col] = CoefListWave[j][col]
4633                                                endif
4634                                                break
4635                                        endif
4636                                endfor
4637                                continue                // skip incrementing coefIndex
4638                        elseif (OKtoSetLinkRows)                // indent 3
4639                                linktext = (CoefListWave[i][1])[5,strlen(CoefListWave[i][1])-1]
4640                                for (j = 0; j < nTotalCoefs; j += 1)            // indent 4
4641                                        if ( (CmpStr(linktext, CoefListWave[j][1]) == 0) || (CmpStr(CoefListWave[i][1], CoefListWave[j][1]) == 0) )             // indent 5
4642                                                // we have found the master row                                         or one of the linked rows
4643                                                if (col == 3)           // indent 6
4644                                                        if (w[coefIndex][0])
4645                                                                CoefSelWave[j][col] = 0x20 + 0x10
4646                                                        else
4647                                                                CoefSelWave[j][col] = 0x20
4648                                                        endif
4649                                                else            // indent 6
4650                                                        sprintf dumstr, formatStr, w[coefIndex][0]
4651                                                        nstr = strlen(dumstr)
4652                                                        Variable k
4653                                                        for (k = 0; k < nstr; k += 1)
4654                                                                if (char2num(dumstr[k]) != char2num(" "))
4655                                                                        break
4656                                                                endif
4657                                                        endfor
4658                                                        if (k > 0)
4659                                                                dumstr = dumstr[k, strlen(dumstr)-1]
4660                                                        endif
4661                                                        CoefListWave[j][col] = dumstr
4662                                                endif           // indent 6
4663//                                              coefIndex += 1
4664                                        endif           // indent 5
4665                                endfor          // indent 4
4666                        endif           // indent 3
4667                endif           // indent 2
4668                coefIndex += 1
4669        endfor          // indent 1
4670end
4671
4672static Function SaveCoefListToWave(w, col, SaveOnlySelectedCells, OKToSaveLinkCells)
4673        Wave w
4674        Variable col
4675        Variable SaveOnlySelectedCells
4676        Variable OKToSaveLinkCells
4677       
4678        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4679        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
4680        Variable ntotalCoefs = totalCoefsFromCoefList()
4681        Variable i
4682        Variable waveIndex = 0
4683       
4684        for (i = 0; i < ntotalCoefs; i += 1)
4685                if (OKToSaveLinkCells || !IsLinkText(CoefListWave[i][1]))
4686                        if ( SaveOnlySelectedCells && !IsRowSelected(CoefSelWave, i) )
4687                                continue
4688                        endif
4689                        if (col == 3)
4690                                w[waveIndex] = ((CoefSelWave[i][col] & 0x10) != 0)
4691                        else
4692                                w[waveIndex] = str2num(CoefListWave[i][col])
4693                        endif
4694                        waveIndex += 1
4695                endif
4696        endfor
4697end
4698
4699static Function FindSelectedRows(SelectionWave)
4700        Wave SelectionWave
4701       
4702        Variable rows = DimSize(SelectionWave, 0)
4703        Variable cols = DimSize(SelectionWave, 1)
4704        Variable i,j
4705        Variable rowsSelected = 0
4706       
4707        for (i = 0; i < rows; i += 1)
4708                for (j = 0; j < cols; j += 1)
4709                        if (IsRowSelected(SelectionWave, i))
4710                                rowsSelected += 1
4711                                break;
4712                        endif
4713                endfor
4714        endfor
4715       
4716        return rowsSelected;
4717end
4718
4719static Function IsRowSelected(SelectionWave, row)
4720        Wave SelectionWave
4721        Variable row
4722       
4723        Variable cols = DimSize(SelectionWave, 1)
4724        Variable j
4725       
4726        for (j = 0; j < cols; j += 1)
4727                if (SelectionWave[row][j] & 9)
4728                        return 1
4729                        break;
4730                endif
4731        endfor
4732       
4733        return 0;
4734end
4735
4736//SRK - new function to generate a report (always)
4737Function Generate_GF_Report(topGraph,GF_resultStr)
4738        String topGraph,GF_resultStr
4739       
4740        String nb = "GF_Report"
4741        String str=""
4742       
4743        // bring report up
4744        DoWindow/F GF_Report
4745        if (V_flag == 0)                // Report notebook doesn't exist ?
4746                NewNotebook/W=(10,45,550,620)/F=1/N=GF_Report as "Global Fit Report"
4747        endif
4748        // delete old stuff
4749        Notebook $nb selection={startOfFile, endOfFile}, text="\r", selection={startOfFile, startOfFile}
4750       
4751        //setup
4752        Notebook $nb defaultTab=36, statusWidth=252, pageMargins={44,44,44,44}          //44 points = 0.6" margin all around
4753        Notebook $nb showRuler=1, rulerUnits=1, updating={1, 60}
4754        Notebook $nb newRuler=Normal, justification=0, margins={0,0,524}, spacing={0,0,0}, tabs={}, rulerDefaults={"Geneva",10,0,(0,0,0)}
4755//     
4756        // insert title
4757        Notebook $nb newRuler=Title, justification=1, rulerDefaults={"Times", 16, 1, (0, 0, 0)}
4758        sprintf str, "Global Fit Completed %s, %s\r\r",Secs2Date(datetime, 0), time()
4759        Notebook $nb ruler=Title, text=str
4760       
4761        //the text
4762        Notebook $nb ruler=Normal
4763        Notebook $nb  margins={0,0,524}, tabs={63 + 3*8192}
4764        Notebook $nb text=GF_resultStr
4765       
4766        //the graph
4767        Notebook $nb picture={$topGraph(0, 0, 400, 300), 0, 1}, text="\r"
4768       
4769        // show the top of the report
4770        Notebook $nb  selection= {startOfFile, startOfFile},  findText={"", 1}
4771       
4772        //save the notebook and the graphic file
4773//      if(yesSave)
4774                String dataFileStr="",nameStr
4775                sscanf StringFromList(4,GF_ResultStr,"\r"),"Data Set:%s",dataFileStr            //reads the 5th line to find the data set name
4776//              String nameStr=CleanupName(func,0)
4777//              nameStr = nameStr[0,8]  //shorten the name
4778                nameStr = "GF_"+dataFileStr
4779                //make sure the name is no more than 31 characters
4780                namestr = namestr[0,30]         //if shorter than 31, this will NOT pad to 31 characters
4781                Print "file saved as ",nameStr
4782                SaveNotebook /O/P=home/S=2 $nb as nameStr
4783//              //save the graph separately as a PICT file, 2x screen
4784//              pictStr += nameStr
4785//              pictStr = pictStr[0,28]         //need a shorter name - why?
4786////            DoWindow/F $topGraph
4787//              // E=-5 is png @screen resolution
4788//              // E=2 is PICT @2x screen resolution
4789/////           SavePICT /E=-5/O/P=home /I/W=(0,0,3,3) as pictStr
4790//              SavePICT /E=-5/O/P=home/WIN=$topGraph /W=(0,0,400,300) as pictStr
4791//      Endif
4792       
4793        return(0)
4794end
4795
4796
4797
4798
Note: See TracBrowser for help on using the repository browser.