source: sans/Dev/trunk/NCNR_User_Procedures/SANS/Analysis/Models/Packages/GlobalFit/GlobalFit2_NCNR_v40.ipf @ 393

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

DoSaveFileDialog? now takes two optional parameters, fname and suffix that can speed file save/rename, especially when used with the subtract1D operation.

Invariant now has a new macro to solve for the volume fraction.

PNGs are used wherever possible for reports. Gizmo window are still the oddball, and are limited to native platform formats.

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