source: sans/Dev/trunk/NCNR_User_Procedures/Analysis/Packages/GlobalFit/GlobalFit2_NCNR_v40.ipf @ 476

Last change on this file since 476 was 476, checked in by srkline, 14 years ago

Tried to stop the unloading clash of GlobalFit? and SimpleGlobalFit?. The Simple fit depends on GlobalFit?, so it can't be unloaded.

SumSANSModels now automatically finds the number of coefficients, since the coefficients are always in the root: folder. Saves the users a step.

Added more windows to the analysis list in the package loader

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