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

Last change on this file since 157 was 157, checked in by srkline, 16 years ago

First pass at modifictations of WM's GlobalFit2 package. The Experiment template (v3.01) has been modified to load in the new file GlobalFit2_NCNR.ipf (through a new SA_includes_v301), and the old GF file GlobalFit4_NCNR.ipf has been tagged as old so it cannot be accidentally loaded into an experiment. It will eventually be deleted from the project.

My changes in the GlobalFit2 are marked with SRK comments, and there are quite a lot of them (3 days worth) since there were many incomatibilites with STRUCT functions.

The new master includes file is SA_includes_v301.ipf. The old one has been deleted from the project.

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