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

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

Several changes:

New version of ILL_DataReadWrite. Some changes added to Lionel's work to get the transmission calculation working corectly.

Changes to the wrapper to get the cursors on/off working correctly, as well as USANS matrix recalculation during normal fitting and during Global fitting. It may ask to recalculate the matrix occasionally when using the full data set - even though it really doesn't need to - but this is as a precaution.

Re-worked the header of the GRASP-export ASCII data to much more closely match the VAX output. I couldn't find any problem with the data block, so maybe GRASP was having trouble with the header.

File size: 165.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        else
3403                // if masking is not selected, be sure to reset the USANS matrices (if any) to their original, full dimensions
3404                // new function
3405                GFUI_ResetUSANSMatrices(DataSets)  //SRK - if NOT masking, reset any USANS matrices
3406        endif
3407       
3408
3409        // Build the Coefficient wave and CoefNames wave
3410        Make/O/D/N=(nRealCoefs, 3) root:Packages:NewGlobalFit:NewGF_CoefWave
3411        Wave coefWave = root:Packages:NewGlobalFit:NewGF_CoefWave
3412        SetDimLabel 1,1,Hold,coefWave
3413        SetDimLabel 1,2,Epsilon,coefWave
3414        Make/O/T/N=(nRealCoefs) root:Packages:NewGlobalFit:NewGF_CoefficientNames
3415        Wave/T CoefNames = root:Packages:NewGlobalFit:NewGF_CoefficientNames
3416
3417        Variable coefIndex = 0
3418        Variable nTotalCoefs = DimSize(CoefListWave, 0)
3419        for (i = 0; i < nTotalCoefs; i += 1)
3420                if (!IsLinkText(CoefListWave[i][1]))
3421                        coefWave[coefIndex][0] = str2num(CoefListWave[i][2])
3422                        if (numtype(coefWave[coefIndex][0]) != 0)
3423                                TabControl NewGF_TabControl, win=NewGlobalFitPanel,value=1
3424                                NewGF_SetTabControlContent(1)
3425                                CoefSelWave = (CoefSelWave & ~1)
3426                                CoefSelWave[i][2] = 3
3427                                DoAlert 0, "There is a problem with the initial guess value in row "+num2str(i)+": it is not a number."
3428                                return -1
3429                        endif
3430                        coefWave[coefIndex][%Hold] = ((CoefSelWave[i][3] & 0x10) != 0)
3431                        coefWave[coefIndex][%Epsilon] = str2num(CoefListWave[i][4])
3432                        if (numtype(coefWave[coefIndex][%Epsilon]) != 0)
3433                                TabControl NewGF_TabControl, win=NewGlobalFitPanel,value=1
3434                                NewGF_SetTabControlContent(1)
3435                                CoefSelWave = (CoefSelWave & ~1)
3436                                CoefSelWave[i][4] = 3
3437                                DoAlert 0, "There is a problem with the Epsilon value in row "+num2str(i)+": it is not a number."
3438                                return -1
3439                        endif
3440                        CoefNames[coefIndex] = CoefListWave[i][1]
3441                        coefIndex += 1
3442                endif
3443        endfor
3444       
3445        // Build constraint wave, if necessary
3446        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_ConstraintsCheckBox
3447        if (V_value)
3448                NewGF_MakeConstraintWave()
3449                Wave/T/Z ConstraintWave = root:Packages:NewGlobalFit:GFUI_GlobalFitConstraintWave
3450        else
3451                Wave/T/Z ConstraintWave = $""
3452        endif
3453       
3454        // Set options
3455        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoCovarMatrix
3456        if (V_value)
3457                curveFitOptions += NewGFOptionCOV_MATRIX
3458        endif
3459
3460        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_CorrelationMatrixCheckBox
3461        if (V_value)
3462                curveFitOptions += NewGFOptionCOR_MATRIX
3463        endif
3464
3465        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_MakeFitCurvesCheck
3466        if (V_value)
3467                curveFitOptions += NewGFOptionMAKE_FIT_WAVES
3468        endif
3469
3470        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea AppendResultsCheck
3471        if (V_value)
3472                curveFitOptions += NewGFOptionAPPEND_RESULTS
3473        endif
3474       
3475        NVAR FitCurvePoints = root:Packages:NewGlobalFit:FitCurvePoints
3476       
3477        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoResidualCheck
3478        if (V_value)
3479                curveFitOptions += NewGFOptionCALC_RESIDS
3480        endif
3481       
3482        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_DoDestLogSpacingCheck
3483        if (V_value)
3484                curveFitOptions += NewGFOptionLOG_DEST_WAVE
3485        endif
3486       
3487        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_Quiet
3488        if (V_value)
3489                curveFitOptions += NewGFOptionQUIET
3490        endif
3491
3492        ControlInfo/W=NewGlobalFitPanel#NewGF_GlobalControlArea NewGF_FitProgressGraphCheckBox
3493        if (V_value)
3494                curveFitOptions += NewGFOptionFIT_GRAPH
3495        endif
3496
3497        Variable err = DoNewGlobalFit(FitFuncNames, DataSets, LinkageMatrix, coefWave, CoefNames, ConstraintWave, curveFitOptions, FitCurvePoints, 1)
3498
3499        if (!err)
3500                SetCoefListFromWave(coefWave, 2, 0, 0)
3501        endif
3502end
3503
3504static Function/S MakeHoldString(CoefWave, quiet, justTheString)
3505        Wave CoefWave
3506        Variable quiet
3507        Variable justTheString
3508       
3509        String HS=""
3510
3511        Variable HoldCol = FindDimLabel(CoefWave, 1, "Hold")
3512        Variable nHolds = 0
3513        if (HoldCol > 0)
3514                if (!justTheString)
3515                        HS="/H=\""
3516                endif
3517                Variable nCoefs=DimSize(CoefWave, 0)
3518                Variable i
3519                for (i = 0; i < nCoefs; i += 1)
3520                        if (CoefWave[i][HoldCol])
3521                                HS += "1"
3522                                nHolds += 1
3523                        else
3524                                HS += "0"
3525                        endif
3526                endfor
3527                if (nHolds == 0)
3528                        return ""                       // ******** EXIT ***********
3529                endif
3530                // work from the end of the string removing extraneous zeroes
3531                if (strlen(HS) > 1)
3532                        for (i = strlen(HS)-1; i >= 0; i -= 1)
3533                                if (CmpStr(HS[i], "1") == 0)
3534                                        break
3535                                endif
3536                        endfor
3537                        if (i > 0)
3538                                HS = HS[0,i]
3539                        endif
3540                endif
3541                if (!justTheString)
3542                        HS += "\""
3543                endif
3544//              if (!quiet)
3545//                      print "Hold String=", HS
3546//              endif
3547                return HS                               // ******** EXIT ***********
3548        else
3549                return ""                               // ******** EXIT ***********
3550        endif
3551end
3552
3553//***********************************
3554//
3555// Constraints
3556//
3557//***********************************
3558
3559static Function ConstraintsCheckProc(ctrlName,checked) : CheckBoxControl
3560        String ctrlName
3561        Variable checked
3562       
3563        Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3564        Variable NumSets = DimSize(ListWave, 0)
3565        Variable i
3566
3567        if (checked)
3568                if (NumSets == 0)
3569                        CheckBox NewGF_ConstraintsCheckBox, win=GlobalFitPanel, value=0
3570                        DoAlert 0, "You cannot add constraints until you have selected data sets"
3571                        return 0
3572                else
3573                        NVAR/Z NewGF_RebuildCoefListNow = root:Packages:NewGlobalFit:NewGF_RebuildCoefListNow
3574                        if (!NVAR_Exists(NewGF_RebuildCoefListNow) || NewGF_RebuildCoefListNow)
3575                                NewGF_RebuildCoefListWave()
3576                        endif
3577                        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
3578                        Variable totalParams = 0
3579                        Variable CoefSize = DimSize(CoefListWave, 0)
3580                        for (i = 0; i < CoefSize; i += 1)
3581                                if (!IsLinkText(CoefListWave[i][1]))
3582                                        totalParams += 1
3583                                endif
3584                        endfor
3585
3586                        String saveDF = GetDatafolder(1)
3587                        SetDatafolder root:Packages:NewGlobalFit
3588                       
3589                        Wave/T/Z SimpleConstraintsListWave
3590                        if (!(WaveExists(SimpleConstraintsListWave) && (DimSize(SimpleConstraintsListWave, 0) == TotalParams)))
3591                                Make/O/N=(TotalParams, 5)/T SimpleConstraintsListWave=""
3592                        endif
3593                        Variable CoefIndex = 0
3594                        for (i = 0; i < CoefSize; i += 1)
3595                                if (!IsLinkText(CoefListWave[i][1]))
3596                                        SimpleConstraintsListWave[CoefIndex][0] = "K"+num2istr(CoefIndex)
3597                                        SimpleConstraintsListWave[CoefIndex][1] = CoefListWave[i][1]
3598                                        SimpleConstraintsListWave[CoefIndex][3] = "< K"+num2istr(CoefIndex)+" <"
3599                                        CoefIndex += 1
3600                                endif
3601                        endfor
3602                        Make/O/N=(TotalParams,5) SimpleConstraintsSelectionWave
3603                        SimpleConstraintsSelectionWave[][0] = 0         // K labels
3604                        SimpleConstraintsSelectionWave[][1] = 0         // coefficient labels
3605                        SimpleConstraintsSelectionWave[][2] = 2         // editable- greater than constraints
3606                        SimpleConstraintsSelectionWave[][3] = 0         // "< Kn <"
3607                        SimpleConstraintsSelectionWave[][4] = 2         // editable- less than constraints
3608                        SetDimLabel 1, 0, 'Kn', SimpleConstraintsListWave
3609                        SetDimLabel 1, 1, 'Actual Coefficient', SimpleConstraintsListWave
3610                        SetDimLabel 1, 2, 'Min', SimpleConstraintsListWave
3611                        SetDimLabel 1, 3, ' ', SimpleConstraintsListWave
3612                        SetDimLabel 1, 4, 'Max', SimpleConstraintsListWave
3613                       
3614                        Wave/Z/T MoreConstraintsListWave
3615                        if (!WaveExists(MoreConstraintsListWave))
3616                                Make/N=(1,1)/T/O  MoreConstraintsListWave=""
3617                                Make/N=(1,1)/O MoreConstraintsSelectionWave=6
3618                                SetDimLabel 1,0,'Enter Constraint Expressions', MoreConstraintsListWave
3619                        endif
3620                        MoreConstraintsSelectionWave=6
3621                       
3622                        SetDatafolder $saveDF
3623                       
3624                        if (WinType("NewGF_GlobalFitConstraintPanel") > 0)
3625                                DoWindow/F NewGF_GlobalFitConstraintPanel
3626                        else
3627                                fNewGF_GlobalFitConstraintPanel()
3628                        endif
3629                endif
3630        endif
3631End
3632
3633static Function fNewGF_GlobalFitConstraintPanel()
3634
3635        NewPanel /W=(45,203,451,568)
3636        DoWindow/C NewGF_GlobalFitConstraintPanel
3637        AutoPositionWindow/M=0/E/R=NewGlobalFitPanel NewGF_GlobalFitConstraintPanel
3638
3639        GroupBox SimpleConstraintsGroup,pos={5,7},size={394,184},title="Simple Constraints"
3640        Button SimpleConstraintsClearB,pos={21,24},size={138,20},proc=WM_NewGlobalFit1#SimpleConstraintsClearBProc,title="Clear List"
3641        ListBox constraintsList,pos={12,49},size={380,127},listwave=root:Packages:NewGlobalFit:SimpleConstraintsListWave
3642        ListBox constraintsList,selWave=root:Packages:NewGlobalFit:SimpleConstraintsSelectionWave, mode=7
3643        ListBox constraintsList,widths={30,189,50,40,50}, editStyle= 1,frame=2,userColumnResize=1
3644
3645        GroupBox AdditionalConstraintsGroup,pos={5,192},size={394,138},title="Additional Constraints"
3646        ListBox moreConstraintsList,pos={12,239},size={380,85}, listwave=root:Packages:NewGlobalFit:MoreConstraintsListWave
3647        ListBox moreConstraintsList,selWave=root:Packages:NewGlobalFit:MoreConstraintsSelectionWave, mode=4
3648        ListBox moreConstraintsList, editStyle= 1,frame=2,userColumnResize=1
3649        Button NewConstraintLineButton,pos={21,211},size={138,20},title="Add a Line", proc=WM_NewGlobalFit1#NewGF_NewCnstrntLineButtonProc
3650        Button RemoveConstraintLineButton01,pos={185,211},size={138,20},title="Remove Selection", proc=WM_NewGlobalFit1#RemoveConstraintLineButtonProc
3651
3652        Button GlobalFitConstraintsDoneB,pos={6,339},size={50,20},proc=WM_NewGlobalFit1#GlobalFitConstraintsDoneBProc,title="Done"
3653EndMacro
3654
3655static Function SimpleConstraintsClearBProc(ctrlName) : ButtonControl
3656        String ctrlName
3657
3658        Wave/Z/T SimpleConstraintsListWave = root:Packages:NewGlobalFit:SimpleConstraintsListWave
3659        SimpleConstraintsListWave[][2] = ""
3660        SimpleConstraintsListWave[][4] = ""
3661End
3662
3663static Function NewGF_NewCnstrntLineButtonProc(ctrlName) : ButtonControl
3664        String ctrlName
3665
3666        Wave/Z/T MoreConstraintsListWave = root:Packages:NewGlobalFit:MoreConstraintsListWave
3667        Wave/Z MoreConstraintsSelectionWave = root:Packages:NewGlobalFit:MoreConstraintsSelectionWave
3668        Variable nRows = DimSize(MoreConstraintsListWave, 0)
3669        InsertPoints nRows, 1, MoreConstraintsListWave, MoreConstraintsSelectionWave
3670        MoreConstraintsListWave[nRows] = ""
3671        MoreConstraintsSelectionWave[nRows] = 6
3672        Redimension/N=(nRows+1,1) MoreConstraintsListWave, MoreConstraintsSelectionWave
3673End
3674
3675static Function RemoveConstraintLineButtonProc(ctrlName) : ButtonControl
3676        String ctrlName
3677
3678        Wave/Z/T MoreConstraintsListWave = root:Packages:NewGlobalFit:MoreConstraintsListWave
3679        Wave/Z MoreConstraintsSelectionWave = root:Packages:NewGlobalFit:MoreConstraintsSelectionWave
3680        Variable nRows = DimSize(MoreConstraintsListWave, 0)
3681        Variable i = 0
3682        do
3683                if (MoreConstraintsSelectionWave[i] & 1)
3684                        if (nRows == 1)
3685                                MoreConstraintsListWave[0] = ""
3686                                MoreConstraintsSelectionWave[0] = 6
3687                        else
3688                                DeletePoints i, 1, MoreConstraintsListWave, MoreConstraintsSelectionWave
3689                                nRows -= 1
3690                        endif
3691                else
3692                        i += 1
3693                endif
3694        while (i < nRows)
3695        Redimension/N=(nRows,1) MoreConstraintsListWave, MoreConstraintsSelectionWave
3696End
3697
3698
3699static Function GlobalFitConstraintsDoneBProc(ctrlName) : ButtonControl
3700        String ctrlName
3701
3702        DoWindow/K NewGF_GlobalFitConstraintPanel
3703End
3704
3705static Function NewGF_MakeConstraintWave()
3706
3707        Wave/Z/T SimpleConstraintsListWave = root:Packages:NewGlobalFit:SimpleConstraintsListWave
3708        Wave/Z/T MoreConstraintsListWave = root:Packages:NewGlobalFit:MoreConstraintsListWave
3709       
3710        Make/O/T/N=0 root:Packages:NewGlobalFit:GFUI_GlobalFitConstraintWave
3711        Wave/T GlobalFitConstraintWave = root:Packages:NewGlobalFit:GFUI_GlobalFitConstraintWave
3712        Variable nextRow = 0
3713        String constraintExpression
3714        Variable i, nPnts=DimSize(SimpleConstraintsListWave, 0)
3715        for (i=0; i < nPnts; i += 1)
3716                if (strlen(SimpleConstraintsListWave[i][2]) > 0)
3717                        InsertPoints nextRow, 1, GlobalFitConstraintWave
3718                        sprintf constraintExpression, "K%d > %s", i, SimpleConstraintsListWave[i][2]
3719                        GlobalFitConstraintWave[nextRow] = constraintExpression
3720                        nextRow += 1
3721                endif
3722                if (strlen(SimpleConstraintsListWave[i][4]) > 0)
3723                        InsertPoints nextRow, 1, GlobalFitConstraintWave
3724                        sprintf constraintExpression, "K%d < %s", i, SimpleConstraintsListWave[i][4]
3725                        GlobalFitConstraintWave[nextRow] = constraintExpression
3726                        nextRow += 1
3727                endif
3728        endfor
3729       
3730        nPnts = DimSize(MoreConstraintsListWave, 0)
3731        for (i = 0; i < nPnts; i += 1)
3732                if (strlen(MoreConstraintsListWave[i]) > 0)
3733                        InsertPoints nextRow, 1, GlobalFitConstraintWave
3734                        GlobalFitConstraintWave[nextRow] = MoreConstraintsListWave[i]
3735                        nextRow += 1
3736                endif
3737        endfor
3738end
3739
3740//***********************************
3741//
3742// Weighting
3743//
3744//***********************************
3745
3746static Function NewGF_WeightingCheckProc(ctrlName,checked) : CheckBoxControl
3747        String ctrlName
3748        Variable checked
3749       
3750        if (checked)
3751                Wave/T ListWave = root:Packages:NewGlobalFit:NewGF_DataSetListWave
3752                Variable numSets = DimSize(ListWave, 0)
3753
3754                if (NumSets == 0)
3755                        CheckBox NewGF_WeightingCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea, value=0
3756                        DoAlert 0, "You cannot choose weighting waves until you have selected data sets."
3757                        return 0
3758                else
3759                        String saveDF = GetDatafolder(1)
3760                        SetDatafolder root:Packages:NewGlobalFit
3761                       
3762                        Wave/T/Z WeightingListWave
3763                        if (!(WaveExists(WeightingListWave) && (DimSize(WeightingListWave, 0) == NumSets)))
3764                                Make/O/N=(NumSets, 2)/T WeightingListWave=""
3765                        endif
3766                        WeightingListWave[][0] = ListWave[p][0][1]
3767                        Make/O/N=(NumSets, 2) WeightingSelectionWave
3768                        WeightingSelectionWave[][0] = 0         // Data Sets
3769                        WeightingSelectionWave[][1] = 0         // Weighting Waves; not editable- select from menu
3770                        SetDimLabel 1, 0, 'Data Set', WeightingListWave
3771                        SetDimLabel 1, 1, 'Weight Wave', WeightingListWave
3772                       
3773                        SetDatafolder $saveDF
3774                       
3775                        if (WinType("NewGF_WeightingPanel") > 0)
3776                                DoWindow/F NewGF_WeightingPanel
3777                        else
3778                                fNewGF_WeightingPanel()
3779                        endif
3780                       
3781//                      Variable/G root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD = NumVarOrDefault("root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD", 1)
3782                        Variable/G root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD = 1                //SRK force StdDev radio button
3783                        NVAR GlobalFit_WeightsAreSD = root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD
3784                        if (GlobalFit_WeightsAreSD)
3785                                WeightsSDRadioProc("WeightsSDRadio",1)
3786                        else
3787                                WeightsSDRadioProc("WeightsInvSDRadio",1)
3788                        endif
3789                                               
3790                endif
3791        endif   
3792end
3793
3794static Function fNewGF_WeightingPanel() : Panel
3795
3796        NewPanel /W=(339,193,745,408)
3797        DoWindow/C NewGF_WeightingPanel
3798        AutoPositionWindow/M=0/E/R=NewGlobalFitPanel NewGF_WeightingPanel
3799       
3800        ListBox WeightWaveListBox,pos={9,63},size={387,112}, mode=10, listWave = root:Packages:NewGlobalFit:WeightingListWave,userColumnResize=1
3801        ListBox WeightWaveListBox, selWave = root:Packages:NewGlobalFit:WeightingSelectionWave, frame=2,proc=WM_NewGlobalFit1#NewGF_WeightListProc
3802
3803        Button GlobalFitWeightDoneButton,pos={24,186},size={50,20},proc=WM_NewGlobalFit1#GlobalFitWeightDoneButtonProc,title="Done"
3804        Button GlobalFitWeightCancelButton,pos={331,186},size={50,20},proc=WM_NewGlobalFit1#GlobalFitWeightCancelButtonProc,title="Cancel"
3805
3806//SRK - disable - simply click on the row to set, based on name structure
3807        PopupMenu GlobalFitWeightWaveMenu,pos={9,5},size={152,20},title="Select Weight Wave"
3808        PopupMenu GlobalFitWeightWaveMenu,mode=0,value= #"WM_NewGlobalFit1#ListPossibleWeightWaves()", proc=WM_NewGlobalFit1#WeightWaveSelectionMenu
3809        PopupMenu GlobalFitWeightWaveMenu,disable=2
3810//eSRK
3811
3812//      Button WeightClearSelectionButton,pos={276,5},size={120,20},proc=WM_NewGlobalFit1#WeightClearSelectionButtonProc,title="Clear Selection"
3813//      Button WeightClearAllButton,pos={276,32},size={120,20},proc=WM_NewGlobalFit1#WeightClearSelectionButtonProc,title="Clear All"
3814
3815        GroupBox WeightStdDevRadioGroup,pos={174,4},size={95,54},title="Weights  are"
3816
3817        CheckBox WeightsSDRadio,pos={185,22},size={60,14},proc=WM_NewGlobalFit1#WeightsSDRadioProc,title="Std. Dev."
3818        CheckBox WeightsSDRadio,value= 1, mode=1
3819        CheckBox WeightsInvSDRadio,pos={185,38},size={73,14},proc=WM_NewGlobalFit1#WeightsSDRadioProc,title="1/Std. Dev."
3820        CheckBox WeightsInvSDRadio,value= 0, mode=1
3821EndMacro
3822
3823static Function NewGF_WeightListProc(ctrlName,row,col,event) : ListBoxControl
3824        String ctrlName     // name of this control
3825        Variable row        // row if click in interior, -1 if click in title
3826        Variable col        // column number
3827        Variable event      // event code
3828       
3829        if (event == 1)
3830                Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3831                Variable NumSets = DimSize(WeightingListWave, 0)
3832                if ( (row == -1) && (col == 1) )
3833                        Wave WeightingSelWave = root:Packages:NewGlobalFit:WeightingSelectionWave
3834                        WeightingSelWave[][1] = 1
3835                elseif ( (col == 1) && (row >= 0) && (row < NumSets) )
3836                        if (GetKeyState(0) == 0)
3837                                Wave/Z w = $(WeightingListWave[row][0])
3838                                if (WaveExists(w))
3839                                        //SRK - since I enforce the loading and naming, bypass the selection
3840                                        //String RowsText = num2str(DimSize(w, 0))
3841                                        //PopupContextualMenu "_calculated_;"+WaveList("*",";","MINROWS:"+RowsText+",MAXROWS:"+RowsText+",DIMS:1,CMPLX:0,TEXT:0,BYTE:0,WORD:0,INTEGER:0")
3842                                       
3843                                        //if (V_flag > 0)
3844                                        //      Wave/Z w = $S_selection
3845                                        //      if (WaveExists(w))
3846                                        //              WeightingListWave[row][1] = GetWavesDataFolder(w, 2)
3847                                        //      endif
3848                                        //endif
3849                                        String yStr = WeightingListWave[row][0]
3850                                        yStr = RemoveEnding(yStr , "i")
3851                                        WeightingListWave[row][1] = yStr + "s"
3852                                        //eSRK
3853                                endif
3854                        endif
3855                endif
3856        endif
3857end
3858
3859static Function GlobalFitWeightDoneButtonProc(ctrlName) : ButtonControl
3860        String ctrlName
3861
3862        Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3863        Variable NumSets = DimSize(WeightingListWave, 0)
3864       
3865        Variable i
3866        for (i = 0; i < NumSets; i += 1)
3867                Wave/Z w = $(WeightingListWave[i][1])
3868                if (!WaveExists(w))
3869                        ListBox WeightWaveListBox, win=NewGF_WeightingPanel, selRow = i
3870                        DoAlert 0, "The wave \""+WeightingListWave[i][1]+"\" does not exist."
3871                        WeightingListWave[i][1] = ""
3872                        return -1
3873                endif
3874        endfor
3875               
3876        DoWindow/K NewGF_WeightingPanel
3877End
3878
3879static Function GlobalFitWeightCancelButtonProc(ctrlName) : ButtonControl
3880        String ctrlName
3881
3882        DoWindow/K NewGF_WeightingPanel
3883        CheckBox NewGF_WeightingCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea, value=0
3884End
3885
3886static Function/S ListPossibleWeightWaves()
3887
3888        Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3889        Wave/Z WeightingSelectionWave=root:Packages:NewGlobalFit:WeightingSelectionWave
3890
3891        String DataSetName=""
3892        Variable i
3893       
3894        ControlInfo/W=NewGF_WeightingPanel WeightWaveListBox
3895        DataSetName = WeightingListWave[V_value][0]
3896       
3897        if (strlen(DataSetName) == 0)
3898                return "No Selection;"
3899        endif
3900       
3901        Wave/Z ds = $DataSetName
3902        if (!WaveExists(ds))
3903                return "Bad Data Set:"+DataSetName+";"
3904        endif
3905       
3906        Variable numpoints = DimSize(ds, 0)
3907        String theList = ""
3908        i=0
3909        do
3910                Wave/Z w = WaveRefIndexed("", i, 4)
3911                if (!WaveExists(w))
3912                        break
3913                endif
3914                if ( (DimSize(w, 0) == numpoints) && (WaveType(w) & 6) )                // select floating-point waves with the right number of points
3915                        theList += NameOfWave(w)+";"
3916                endif
3917                i += 1
3918        while (1)
3919       
3920        if (i == 0)
3921                return "None Available;"
3922        endif
3923       
3924        return theList
3925end
3926
3927static Function WeightWaveSelectionMenu(ctrlName,popNum,popStr) : PopupMenuControl
3928        String ctrlName
3929        Variable popNum
3930        String popStr
3931
3932        Wave/Z w = $popStr
3933        if (WaveExists(w))
3934                Wave/T WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3935                Wave WeightingSelWave = root:Packages:NewGlobalFit:WeightingSelectionWave
3936                Variable nrows = DimSize(WeightingListWave, 0)
3937                Variable i
3938                for (i = 0; i < nrows; i += 1)
3939                        if ( (WeightingSelWave[i][0] & 1) || (WeightingSelWave[i][1]) )
3940                                WeightingListWave[i][1] = GetWavesDatafolder(w, 2)
3941                        endif
3942                endfor
3943        endif
3944end
3945
3946//static Function WeightClearSelectionButtonProc(ctrlName) : ButtonControl
3947//      String ctrlName
3948//
3949//      Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3950//      StrSwitch (ctrlName)
3951//              case "WeightClearSelectionButton":
3952//                      Wave WeightingSelWave = root:Packages:NewGlobalFit:WeightingSelectionWave
3953//                      Variable nrows = DimSize(WeightingListWave, 0)
3954//                      Variable i
3955//                      for (i = 0; i < nrows; i += 1)
3956//                              if ( (WeightingSelWave[i][0] & 1) || (WeightingSelWave[i][1]) )
3957//                                      WeightingListWave[i][1] = ""
3958//                              endif
3959//                      endfor
3960//                      break;
3961//              case "WeightClearAllButton":
3962//                      WeightingListWave[][1] = ""
3963//                      break;
3964//      endswitch
3965//End
3966
3967static Function WeightsSDRadioProc(name,value)
3968        String name
3969        Variable value
3970       
3971        NVAR GlobalFit_WeightsAreSD= root:Packages:NewGlobalFit:GlobalFit_WeightsAreSD
3972       
3973        strswitch (name)
3974                case "WeightsSDRadio":
3975                        GlobalFit_WeightsAreSD = 1
3976                        break
3977                case "WeightsInvSDRadio":
3978                        GlobalFit_WeightsAreSD = 0
3979                        break
3980        endswitch
3981        CheckBox WeightsSDRadio, win=NewGF_WeightingPanel, value= GlobalFit_WeightsAreSD==1
3982        CheckBox WeightsInvSDRadio, win=NewGF_WeightingPanel, value= GlobalFit_WeightsAreSD==0
3983End
3984
3985// This function is strictly for the use of the Global Analysis control panel. It assumes that the DataSets
3986// wave so far has just two columns, the Y and X wave columns
3987static Function GFUI_AddWeightWavesToDataSets(DataSets)
3988        Wave/T DataSets
3989       
3990        Wave/T/Z WeightingListWave=root:Packages:NewGlobalFit:WeightingListWave
3991       
3992        Redimension/N=(-1, 3) DataSets
3993        SetDimLabel 1, 2, Weights, DataSets
3994       
3995        Variable numSets = DimSize(DataSets, 0)
3996        Variable i
3997        for (i = 0; i < NumSets; i += 1)
3998                Wave/Z w = $(WeightingListWave[i][1])
3999                if (WaveExists(w))
4000                        wave/Z yw = $(DataSets[i][0])
4001                        if (WaveExists(yw) && (numpnts(w) != numpnts(yw)))
4002                                DoAlert 0,"The weighting wave \""+WeightingListWave[i][1]+"\" has a different number points than Y wave \""+(DataSets[i][0])+"\""
4003                                return -1
4004                        endif
4005                        DataSets[i][2] = WeightingListWave[i][1]
4006                else
4007                        Redimension/N=(-1,2) DataSets
4008                        DoAlert 0,"The weighting wave \""+WeightingListWave[i][1]+"\" for Y wave \""+(DataSets[i][0])+"\" does not exist."
4009                        return -1
4010                endif
4011        endfor
4012       
4013        return 0
4014end
4015
4016static Function GFUI_AddMaskWavesToDataSets(DataSets)
4017        Wave/T DataSets
4018       
4019        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4020       
4021        Variable startingNCols = DimSize(DataSets, 1)
4022        Redimension/N=(-1, startingNCols+1) DataSets
4023        SetDimLabel 1, startingNCols, Masks, DataSets
4024       
4025        Variable numSets = DimSize(DataSets, 0)
4026        Variable i
4027        Variable pt1,pt2,mPt1,mPt2
4028        String str,noteStr,DF
4029       
4030        for (i = 0; i < NumSets; i += 1)
4031                Wave/Z w = $(MaskingListWave[i][1])
4032                if (WaveExists(w))
4033                        wave/Z yw = $(DataSets[i][0])
4034                        if (WaveExists(yw) && (numpnts(w) != numpnts(yw)))
4035                                DoAlert 0,"The mask wave \""+MaskingListWave[i][1]+"\" has a different number points than Y wave \""+(DataSets[i][0])+"\""
4036                                return -1
4037                        endif
4038                        DataSets[i][startingNCols] = MaskingListWave[i][1]
4039                        //SRK - recalculate the resolution matrix if not already present
4040                        // start of bits to add
4041                        str=DataSets[i][0]              //this seems to work
4042                        DF=ParseFilePath(1, str, ":", 1, 0)
4043//
4044                        str=str[0,strlen(str)-3]                //remove the "_i" = DataFolder:name
4045                        WAVE resW = $(str+"_res")
4046                        if((dimsize(resW,1) > 4))       //USANS, NxN
4047                                noteStr = note(resW)           
4048                                mPt1 = NumberByKey("P1",noteStr,"=",";")
4049                                mPt2 = NumberByKey("P2",noteStr,"=",";")
4050                                Wave/Z mw = $(DataSets[i][startingNCols])
4051               
4052                                //find the first 1,  then find the zero
4053                                pt1 = 0
4054                                do
4055                                        if(mw[pt1]==1)
4056                                                break
4057                                        endif
4058                                        pt1+=1
4059                                while(pt1<numpnts(mw))
4060                               
4061                                pt2 = pt1
4062                                do
4063                                        if(mw[pt2]==0)
4064                                                break
4065                                        endif
4066                                        pt2+=1
4067                                while(pt2<numpnts(mw))
4068                                pt2 -= 1
4069                                if((mPt1 != pt1) || (mPt2 != pt2) )
4070                                        // need to recalculate
4071                                        USANS_RE_CalcWeights(ParseFilePath(0, str, ":", 1, 0),pt1,pt2)
4072                                endif
4073                        endif
4074                       
4075                       
4076                else                    //SRK !!!! CHANGING THE BEHAVIOR !!!!
4077                        // if no masking wave was specified, use the entire set (==1)
4078//                      Redimension/N=(-1,startingNCols) DataSets
4079//                      DoAlert 0,"The mask wave \""+MaskingListWave[i][1]+"\" for Y wave \""+(DataSets[i][0])+"\" does not exist."
4080//                      return -1
4081
4082                // this will signal the AAOFitFunction to use the full matrix without recalculation
4083
4084                        DataSets[i][startingNCols] = "No Mask"
4085                        //eSRK
4086                endif
4087        endfor
4088       
4089        return 0
4090end
4091
4092// if masking is not checked at all, make sure that the full matrix is used for the USANS data sets
4093// force a recalculate
4094// set all of the data sets to "no mask", even the SANS data
4095// SRK July 2008
4096static Function GFUI_ResetUSANSMatrices(DataSets)
4097        Wave/T DataSets
4098       
4099        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4100       
4101        Variable startingNCols = DimSize(DataSets, 1)
4102        Redimension/N=(-1, startingNCols+1) DataSets
4103        SetDimLabel 1, startingNCols, Masks, DataSets
4104       
4105        Variable numSets = DimSize(DataSets, 0)
4106        Variable i
4107        Variable pt1,pt2,mPt1,mPt2
4108        String str,noteStr,DF
4109       
4110        for (i = 0; i < NumSets; i += 1)
4111
4112                str=DataSets[i][0]              //this seems to work
4113                DF=ParseFilePath(1, str, ":", 1, 0)
4114//
4115                str=str[0,strlen(str)-3]                //remove the "_i" = DataFolder:name
4116                WAVE resW = $(str+"_res")
4117                if((dimsize(resW,1) > 4))       //USANS, NxN
4118                        // always force a recalculation, even though the weights_saved exists
4119                        // seems easier than shuffling.
4120                        Wave data = $(str+"_i")
4121                        Variable len=numpnts(data)
4122                        USANS_RE_CalcWeights(ParseFilePath(0, str, ":", 1, 0),0,len-1)
4123                       
4124//                      noteStr = note(resW)           
4125//                      mPt1 = NumberByKey("P1",noteStr,"=",";")
4126//                      mPt2 = NumberByKey("P2",noteStr,"=",";")
4127//                      Wave/Z mw = $(DataSets[i][startingNCols])
4128//     
4129//                      //find the first 1,  then find the zero
4130//                      pt1 = 0
4131//                      do
4132//                              if(mw[pt1]==1)
4133//                                      break
4134//                              endif
4135//                              pt1+=1
4136//                      while(pt1<numpnts(mw))
4137//                     
4138//                      pt2 = pt1
4139//                      do
4140//                              if(mw[pt2]==0)
4141//                                      break
4142//                              endif
4143//                              pt2+=1
4144//                      while(pt2<numpnts(mw))
4145//                      pt2 -= 1
4146//                      if((mPt1 != pt1) || (mPt2 != pt2) )
4147//                              // need to recalculate
4148//                              USANS_RE_CalcWeights(ParseFilePath(0, str, ":", 1, 0),pt1,pt2)
4149//                      endif
4150                endif
4151       
4152                DataSets[i][startingNCols] = "No Mask"          //no mask for any data set
4153
4154        endfor
4155       
4156        return 0
4157end
4158
4159
4160static Function NewGF_CovMatrixCheckProc(ctrlName,checked) : CheckBoxControl
4161        String ctrlName
4162        Variable checked
4163
4164        if (!checked)
4165                Checkbox NewGF_CorrelationMatrixCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=0
4166        endif
4167End
4168
4169static Function NewGF_CorMatrixCheckProc(ctrlName,checked) : CheckBoxControl
4170        String ctrlName
4171        Variable checked
4172
4173        if (checked)
4174                Checkbox NewGF_DoCovarMatrix, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=1
4175        endif
4176End
4177
4178
4179static Function NewGF_FitCurvesCheckProc(ctrlName,checked) : CheckBoxControl
4180        String ctrlName
4181        Variable checked
4182
4183        if (!checked)
4184                Checkbox NewGF_AppendResultsCheckbox, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=0
4185                Checkbox NewGF_DoResidualCheck, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=0
4186        endif
4187End
4188
4189static Function NewGF_AppendResultsCheckProc(ctrlName,checked) : CheckBoxControl
4190        String ctrlName
4191        Variable checked
4192
4193        if (checked)
4194                Checkbox NewGF_MakeFitCurvesCheck, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=1
4195        endif
4196End
4197
4198static Function NewGF_CalcResidualsCheckProc(ctrlName,checked) : CheckBoxControl
4199        String ctrlName
4200        Variable checked
4201
4202        if (checked)
4203                Checkbox NewGF_MakeFitCurvesCheck, win=NewGlobalFitPanel#NewGF_GlobalControlArea,value=1
4204        endif
4205End
4206
4207
4208//***********************************
4209//
4210// Data masking
4211//
4212//***********************************
4213
4214static Function NewGF_MaskingCheckProc(ctrlName,checked) : CheckBoxControl
4215        String ctrlName
4216        Variable checked
4217       
4218        if (checked)
4219                Wave/T DataSetList = root:Packages:NewGlobalFit:NewGF_DataSetListWave
4220                Variable numSets = DimSize(DataSetList, 0)
4221
4222                if (NumSets == 0)
4223                        CheckBox NewGF_MaskingCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea, value=0
4224                        DoAlert 0, "You cannot add Masking waves until you have selected data sets."
4225                        return 0
4226                else
4227                        String saveDF = GetDatafolder(1)
4228                        SetDatafolder root:Packages:NewGlobalFit
4229                       
4230                        Wave/T/Z MaskingListWave
4231                        if (!(WaveExists(MaskingListWave) && (DimSize(MaskingListWave, 0) == NumSets)))
4232                                Make/O/N=(NumSets, 2)/T MaskingListWave=""
4233                        endif
4234                        MaskingListWave[][0] = DataSetList[p][0][1]
4235                        Make/O/N=(NumSets, 2) MaskingSelectionWave
4236                        MaskingSelectionWave[][0] = 0           // Data Sets
4237                        MaskingSelectionWave[][1] = 0           // Masking Waves; not editable- select from menu
4238                        SetDimLabel 1, 0, 'Data Set', MaskingListWave
4239                        SetDimLabel 1, 1, 'Mask Wave', MaskingListWave
4240                       
4241                        SetDatafolder $saveDF
4242                       
4243                        if (WinType("NewGF_GlobalFitMaskingPanel") > 0)
4244                                DoWindow/F NewGF_GlobalFitMaskingPanel
4245                        else
4246                                fNewGF_GlobalFitMaskingPanel()
4247                        endif
4248                endif
4249        //SRK - hide unused cursors
4250        else
4251                //not checked, remove cursors
4252                Cursor/K A
4253                Cursor/K B
4254                HideInfo
4255        //eSRK
4256        endif   
4257end
4258
4259static Function fNewGF_GlobalFitMaskingPanel() : Panel
4260
4261        NewPanel /W=(339,193,745,408)
4262        DoWindow/C NewGF_GlobalFitMaskingPanel
4263        AutoPositionWindow/M=0/E/R=NewGlobalFitPanel NewGF_GlobalFitMaskingPanel
4264       
4265        ListBox MaskWaveListBox,pos={9,63},size={387,112}, mode=10, listWave = root:Packages:NewGlobalFit:MaskingListWave,userColumnResize=1
4266        //SRK - use my own selection procedure, not the contextual menu in the ListBox
4267//      ListBox MaskWaveListBox, selWave = root:Packages:NewGlobalFit:MaskingSelectionWave, frame=2, proc=WM_NewGlobalFit1#NewGF_MaskListProc
4268        ListBox MaskWaveListBox, selWave = root:Packages:NewGlobalFit:MaskingSelectionWave, frame=2
4269        //eSRK
4270        Button GlobalFitMaskDoneButton,pos={24,186},size={50,20},proc=WM_NewGlobalFit1#GlobalFitMaskDoneButtonProc,title="Done"
4271        Button GlobalFitMaskCancelButton,pos={331,186},size={50,20},proc=WM_NewGlobalFit1#GlobalFitMaskCancelButtonProc,title="Cancel"
4272        PopupMenu GlobalFitMaskWaveMenu,pos={9,5},size={152,20},title="Select Mask Wave"
4273        PopupMenu GlobalFitMaskWaveMenu,mode=0,value= #"WM_NewGlobalFit1#ListPossibleMaskWaves()", proc=WM_NewGlobalFit1#MaskWaveSelectionMenu
4274        Button MaskClearSelectionButton,pos={276,5},size={120,20},proc=WM_NewGlobalFit1#MaskClearSelectionButtonProc,title="Clear Selection"
4275        Button MaskClearAllButton,pos={276,32},size={120,20},proc=WM_NewGlobalFit1#MaskClearSelectionButtonProc,title="Clear All"
4276       
4277        //SRK
4278        Button MaskFromCursorsButton,pos={130,32},size={135,20},proc=MaskFromCursorsButtonProc,title="Mask From Cursors"
4279        ListBox MaskWaveListBox,proc=MaskListBoxSelectionProc
4280        Button MaskShowInfoButton,pos={9,32},size={110,20},proc=MaskShowInfoButtonProc,title="Show Cursors"
4281        //eSRK
4282EndMacro
4283
4284//SRK
4285// make a temporary masking wave from the selected data set
4286// and the cursor positions
4287//
4288Function MaskFromCursorsButtonProc(ctrlName) : ButtonControl
4289        String ctrlName
4290
4291        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4292        Wave selWave = root:Packages:NewGlobalFit:MaskingSelectionWave
4293       
4294        Variable numRow=DimSize(selWave, 0),ii=0
4295        String DataSetName=""
4296        do
4297                if(selWave[ii][0] || selWave[ii][1])
4298                        break
4299                endif
4300                ii+=1
4301        while(ii<numRow)
4302        numRow=ii
4303       
4304        DataSetName = MaskingListWave[numRow][0]                //"root:yTraceName"
4305        Wave w = $DataSetName
4306       
4307        Duplicate/O $DataSetName,$(DataSetName+"mask")  //mask is in root: folder
4308       
4309        MaskingListWave[numRow][1] = DataSetName+"mask"
4310       
4311        Wave mm = $(DataSetName+"mask")
4312        mm=1            //mask nothing as the default
4313       
4314        //set the masking based on the cursors
4315        Make/O/N=2 csrPts
4316        csrPts[0] = xcsr(A)
4317        csrPts[1] = xcsr(B)
4318        Sort csrPts,csrPts              //pt[0] is smaller - guaranteed
4319       
4320        if(csrPts[0] > 0)
4321                mm[0,csrPts[0]-1] = 0
4322        endif
4323        if(csrPts[1] < (numpnts(mm)-1) )
4324                mm[csrPts[1]+1,numpnts(mm)-1] = 0
4325        endif
4326       
4327        Killwaves/Z csrPts     
4328End
4329
4330//SRK
4331Function MaskShowInfoButtonProc(ctrlName) : ButtonControl
4332        String ctrlName
4333        ShowInfo                //topmost graph
4334        return(0)
4335End
4336
4337//SRK
4338// based on the selected data set in the list box, put cursors
4339// on the proper data set, and put them at the right points
4340// if the masking wave exists
4341//
4342Function MaskListBoxSelectionProc(ctrlName,row,col,event)       // : ListboxControl
4343        String ctrlName     // name of this control
4344        Variable row        // row if click in interior, -1 if click in title
4345        Variable col        // column number
4346        Variable event      // event code
4347       
4348        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4349       
4350        String str=MaskingListWave[row][0]              //"root:yTraceName"
4351        Variable ptA=0,ptB=numpnts($(str[5,strlen(str)-1]))-1           //default to end points
4352        WAVE/Z mm = $(str+"mask")
4353        if(waveexists(mm))
4354                FindLevel/P/Q mm,1
4355                ptA = V_LevelX
4356                FindLevel/P/Q/R=[ptA] mm,0
4357                if(V_flag==0)
4358                        ptB = V_LevelX-1                //level was found, use it. otherwise use default
4359                endif
4360        endif
4361        // get the right target window, hopefully the top graph
4362        String tmp= StringFromList(0,WinList("*", ";","WIN:1"),";")             //first graph is "topmost"
4363        Cursor/P/W=$tmp A, $(ParseFilePath(0, str, ":", 1, 0)),ptA                      //just give me the wave name, not the full path
4364        Cursor/P/W=$tmp B, $(ParseFilePath(0, str, ":", 1, 0)),ptB
4365       
4366        return 0            // other return values reserved
4367End
4368
4369static Function NewGF_MaskListProc(ctrlName,row,col,event) : ListBoxControl
4370        String ctrlName     // name of this control
4371        Variable row        // row if click in interior, -1 if click in title
4372        Variable col        // column number
4373        Variable event      // event code
4374       
4375        if (event == 1)
4376                Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4377                Variable numSets = DimSize(MaskingListWave, 0)
4378                if ( (row == -1) && (col == 1) )
4379                        Wave MaskingSelWave = root:Packages:NewGlobalFit:MaskingSelectionWave
4380                        MaskingSelWave[][1] = 1
4381                elseif ( (col == 1) && (row >= 0) && (row < NumSets) )
4382                        if (GetKeyState(0) == 0)
4383                                Wave/Z w = $(MaskingListWave[row][0])
4384                                if (WaveExists(w))
4385                                        String RowsText = num2str(DimSize(w, 0))
4386                                        PopupContextualMenu "_calculated_;"+WaveList("*",";","MINROWS:"+RowsText+",MAXROWS:"+RowsText+",DIMS:1,CMPLX:0,TEXT:0,BYTE:0,WORD:0,INTEGER:0")
4387                                        if (V_flag > 0)
4388                                                Wave/Z w = $S_selection
4389                                                if (WaveExists(w))
4390                                                        MaskingListWave[row][1] = GetWavesDataFolder(w, 2)
4391                                                endif
4392                                        endif
4393                                endif
4394                        endif
4395                endif
4396        endif
4397end
4398
4399static Function GlobalFitMaskDoneButtonProc(ctrlName) : ButtonControl
4400        String ctrlName
4401
4402        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4403        Variable numSets = DimSize(MaskingListWave, 0)
4404
4405        Variable i
4406        for (i = 0; i < NumSets; i += 1)
4407                Wave/Z w = $(MaskingListWave[i][1])
4408                if (!WaveExists(w))
4409                        if (strlen(MaskingListWave[i][1]) != 0)
4410                                ListBox MaskWaveListBox, win=NewGF_GlobalFitMaskingPanel, selRow = i
4411                                DoAlert 0, "The wave \""+MaskingListWave[i][1]+"\" does not exist."
4412                                MaskingListWave[i][1] = ""
4413                                return -1
4414                        endif
4415                endif
4416        endfor
4417               
4418        DoWindow/K NewGF_GlobalFitMaskingPanel
4419End
4420
4421static Function GlobalFitMaskCancelButtonProc(ctrlName) : ButtonControl
4422        String ctrlName
4423
4424        DoWindow/K NewGF_GlobalFitMaskingPanel
4425        CheckBox NewGF_MaskingCheckBox, win=NewGlobalFitPanel#NewGF_GlobalControlArea, value=0
4426End
4427
4428static Function/S ListPossibleMaskWaves()
4429
4430        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4431        Wave/Z MaskingSelectionWave=root:Packages:NewGlobalFit:MaskingSelectionWave
4432        Variable NumSets= DimSize(MaskingListWave, 0)
4433
4434        String DataSetName=""
4435        Variable i
4436       
4437        ControlInfo/W=NewGF_GlobalFitMaskingPanel MaskWaveListBox
4438        DataSetName = MaskingListWave[V_value][0]
4439       
4440        if (strlen(DataSetName) == 0)
4441                return "No Selection;"
4442        endif
4443       
4444        Wave/Z ds = $DataSetName
4445        if (!WaveExists(ds))
4446                return "Unknown Data Set;"
4447        endif
4448       
4449        Variable numpoints = DimSize(ds, 0)
4450        String theList = ""
4451        i=0
4452        do
4453                Wave/Z w = WaveRefIndexed("", i, 4)
4454                if (!WaveExists(w))
4455                        break
4456                endif
4457                if ( (DimSize(w, 0) == numpoints) && (WaveType(w) & 6) )                // select floating-point waves with the right number of points
4458                        theList += NameOfWave(w)+";"
4459                endif
4460                i += 1
4461        while (1)
4462       
4463        if (i == 0)
4464                return "None Available;"
4465        endif
4466       
4467        return theList
4468end
4469
4470static Function MaskWaveSelectionMenu(ctrlName,popNum,popStr) : PopupMenuControl
4471        String ctrlName
4472        Variable popNum
4473        String popStr
4474
4475        Wave/Z w = $popStr
4476        if (WaveExists(w))
4477                Wave/T MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4478                Wave MaskingSelWave = root:Packages:NewGlobalFit:MaskingSelectionWave
4479                Variable nrows = DimSize(MaskingListWave, 0)
4480                Variable i
4481                for (i = 0; i < nrows; i += 1)
4482                        if ( (MaskingSelWave[i][0] & 1) || (MaskingSelWave[i][1]) )
4483                                MaskingListWave[i][1] = GetWavesDatafolder(w, 2)
4484                        endif
4485                endfor
4486        endif
4487end
4488
4489static Function MaskClearSelectionButtonProc(ctrlName) : ButtonControl
4490        String ctrlName
4491
4492        Wave/T/Z MaskingListWave=root:Packages:NewGlobalFit:MaskingListWave
4493        StrSwitch (ctrlName)
4494                case "MaskClearSelectionButton":
4495                        Wave MaskingSelWave = root:Packages:NewGlobalFit:MaskingSelectionWave
4496                        Variable nrows = DimSize(MaskingListWave, 0)
4497                        Variable i
4498                        for (i = 0; i < nrows; i += 1)
4499                                if ( (MaskingSelWave[i][0] & 1) || (MaskingSelWave[i][1]) )
4500                                        MaskingListWave[i][1] = ""
4501                                endif
4502                        endfor
4503                        break;
4504                case "MaskClearAllButton":
4505                        MaskingListWave[][1] = ""
4506                        break;
4507        endswitch
4508End
4509
4510
4511
4512//***********************************
4513//
4514// Load/Save initial guesses from/to a wave
4515//
4516//***********************************
4517
4518Function/S NewGF_ListInitGuessWaves(SelectedOnly, LinkRowsOK)
4519        Variable SelectedOnly
4520        Variable LinkRowsOK
4521
4522        Variable numrows
4523//      ControlInfo/W=NewGlobalFitPanel#Tab1ContentPanel NewGF_InitGuessCopySelCheck
4524        if (SelectedOnly)
4525                numrows = totalSelRealCoefsFromCoefList(LinkRowsOK)
4526        else
4527                numrows = totalRealCoefsFromCoefList(LinkRowsOK)
4528        endif
4529       
4530        String numrowsstr = num2str(numrows)
4531        return WaveList("*", ";", "DIMS:1,MINROWS:"+numrowsstr+",MAXROWS:"+numrowsstr+",BYTE:0,INTEGER:0,WORD:0,CMPLX:0,TEXT:0")
4532end
4533
4534char ctrlName[MAX_OBJ_NAME+1]   Control name.
4535char win[MAX_WIN_PATH+1]        Host (sub)window.
4536STRUCT Rect winRect     Local coordinates of host window.
4537STRUCT Rect ctrlRect    Enclosing rectangle of the control.
4538STRUCT Point mouseLoc   Mouse location.
4539Int32 eventCode Event that caused the procedure to execute. Main event is mouse up=2.
4540String userdata Primary (unnamed) user data. If this changes, it is written back automatically.
4541Int32 popNum    Item number currently selected (1-based).
4542char popStr[MAXCMDLEN]  Contents of current popup item.
4543
4544Function NewGF_SetCoefsFromWaveProc(PU_Struct) : PopupMenuControl
4545        STRUCT WMPopupAction &PU_Struct
4546
4547        if (PU_Struct.eventCode == 2)                   // mouse up
4548                Wave w = $(PU_Struct.popStr)
4549                if (!WaveExists(w))
4550                        DoAlert 0, "The wave you selected does not exist for some reason."
4551                        return 0
4552                endif
4553               
4554                SetCoefListFromWave(w, 2, 0, 0)
4555        endif
4556end
4557
4558Function NewGF_SaveCoefsToWaveProc(PU_Struct) : PopupMenuControl
4559        STRUCT WMPopupAction &PU_Struct
4560
4561        if (PU_Struct.eventCode == 2)                   // mouse up
4562                if (CmpStr(PU_Struct.popStr, "New Wave...") == 0)
4563                        Variable numRowsNeeded = totalRealCoefsFromCoefList(0)
4564                        String newName = NewGF_GetNewWaveName()
4565                        if (strlen(newName) == 0)
4566                                return 0
4567                        endif
4568                        Make/O/N=(numRowsNeeded)/D $newName
4569                        Wave w = $newName
4570                else
4571                        Wave w = $(PU_Struct.popStr)
4572                endif
4573               
4574                SaveCoefListToWave(w, 2, 0, 0)
4575        endif
4576end
4577
4578Function/S NewGF_GetNewWaveName()
4579
4580        String newName
4581        Prompt newName, "Enter a name for the new wave:"
4582        DoPrompt "Get New Wave Name", newName
4583        if (V_flag)
4584                return ""
4585        endif
4586       
4587        return newName
4588end
4589       
4590//***********************************
4591//
4592// Utility functions
4593//
4594//***********************************
4595
4596// returns semicolon-separated list of items in a selected column of a 1D or 2D text wave
4597static Function/S TextWaveToList(twave, column)
4598        Wave/T twave
4599        Variable column
4600       
4601        String returnValue = ""
4602        Variable nRows = DimSize(twave, 0)
4603        Variable i
4604       
4605        for (i = 0; i < nRows; i += 1)
4606                returnValue += (twave[i][column])+";"
4607        endfor
4608       
4609        return returnValue
4610end
4611
4612static Function IsLinkText(theText)
4613        String theText
4614       
4615        return (CmpStr(theText[0,4], "LINK:") == 0)
4616end
4617
4618static Function ItemListedInWave(Item, theWave)
4619        String Item
4620        Wave/T theWave
4621       
4622        return ItemNumberInTextWaveList(Item, theWave) >= 0
4623end
4624
4625static Function ItemNumberInTextWaveList(Item, theWave)
4626        String Item
4627        Wave/T theWave
4628       
4629        Variable i
4630        Variable npnts = DimSize(theWave, 0)
4631        Variable itemNumber = -1
4632       
4633        for (i = 0; i < npnts; i += 1)
4634                if ( (strlen(theWave[i]) > 0) && (CmpStr(theWave[i], Item) == 0) )
4635                        itemNumber = i
4636                        break
4637                endif
4638        endfor
4639       
4640        return itemNumber
4641end
4642
4643// makes a 1D or 2D text wave with each item from a semicolon-separated list in the wave's rows
4644// in the selected column. You are free to fill other columns as you wish.
4645static Function ListToTwave(theList, twaveName, columns, column)
4646        String theList
4647        String twaveName
4648        Variable columns
4649        Variable column
4650       
4651        Variable nRows = ItemsInList(theList)
4652        Variable i
4653       
4654        Make/T/O/N=(nRows, columns) $twaveName
4655        Wave/T twave = $twaveName
4656       
4657        for (i = 0; i < nRows; i += 1)
4658                twave[i][column] = StringFromList(i, theList)
4659        endfor
4660end
4661
4662static Function totalCoefsFromCoefList()
4663
4664        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4665       
4666        return DimSize(CoefListWave, 0)
4667end
4668
4669static Function totalRealCoefsFromCoefList(LinkRowsOK)
4670        Variable LinkRowsOK
4671
4672        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4673
4674        Variable i
4675        Variable totalNonlinkRows = 0
4676        Variable numrows = DimSize(CoefListWave, 0)
4677        for (i = 0; i < numrows; i += 1)
4678                if (LinkRowsOK || !IsLinkText(CoefListWave[i][1]))
4679                        totalNonlinkRows += 1
4680                endif
4681        endfor
4682       
4683        return totalNonlinkRows
4684end
4685
4686static Function totalSelRealCoefsFromCoefList(LinkRowsOK)
4687        Variable LinkRowsOK
4688
4689        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4690        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
4691
4692        Variable i
4693        Variable totalNonlinkRows = 0
4694        Variable numrows = DimSize(CoefListWave, 0)
4695        for (i = 0; i < numrows; i += 1)
4696                if (LinkRowsOK || !IsLinkText(CoefListWave[i][1]))
4697                        if (IsRowSelected(CoefSelWave, i))
4698                                totalNonlinkRows += 1
4699                        endif
4700                endif
4701        endfor
4702       
4703        return totalNonlinkRows
4704end
4705
4706static Function SetCoefListFromWave(w, col, SetOnlySelectedCells, OKtoSetLinkRows)
4707        Wave w
4708        Variable col
4709        Variable SetOnlySelectedCells
4710        Variable OKtoSetLinkRows
4711       
4712        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4713        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
4714
4715        Variable coefIndex = 0;
4716        Variable i,j
4717        Variable nTotalCoefs = DimSize(CoefListWave, 0)
4718       
4719        String formatStr = "%.15g"
4720        if ( (WaveType(w) & 4) == 0)            // it's not a double-precision wave
4721                formatStr = "%.6g"
4722        endif
4723       
4724        for (i = 0; i < nTotalCoefs; i += 1)            // indent 1
4725//              if ( SetOnlySelectedCells && ((CoefSelWave[i][col] & 9) == 0) )
4726                if ( SetOnlySelectedCells && !IsRowSelected(CoefSelWave, i) )
4727                        continue
4728                endif
4729//              if (!OKtoSetLinkRows && !IsLinkText(CoefListWave[i][1]))
4730                if (!IsLinkText(CoefListWave[i][1]))            // indent 2
4731                        // first part sets the coefficient list wave text from the appropriate element in the input wave
4732               
4733                        if (col == 3)
4734                                if (w[coefIndex][0])
4735                                        CoefSelWave[i][col] = 0x20 + 0x10
4736                                else
4737                                        CoefSelWave[i][col] = 0x20
4738                                endif
4739                        else
4740                                string dumstr
4741                                sprintf dumstr, formatStr, w[coefIndex][0]
4742                                Variable nstr = strlen(dumstr)
4743                                for (j = 0; j < nstr; j += 1)
4744                                        if (char2num(dumstr[j]) != char2num(" "))
4745                                                break
4746                                        endif
4747                                endfor
4748                                if (j > 0)
4749                                        dumstr = dumstr[j, strlen(dumstr)-1]
4750                                endif
4751                                CoefListWave[i][col] = dumstr
4752                        endif
4753                else            // indent 2
4754                        string linktext
4755                        // We've hit a link cell (refers to an earlier row)
4756                        //
4757                        // If we are setting the entire wave, rather than setting the value in the row, we should instead copy the value
4758                        // from the row containing the master copy (the row to which the link refers). (first IF block)
4759                        //
4760                        // 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
4761                        // and any other rows that link to it.
4762                        if (!SetOnlySelectedCells)              // indent 3
4763                                // copy linked text from master row when we encounter a linked cell. The links should always be after the cell they link to.
4764                                linktext = (CoefListWave[i][1])[5,strlen(CoefListWave[i][1])-1]
4765                                for (j = 0; j < nTotalCoefs; j += 1)
4766                                        if (CmpStr(linktext, CoefListWave[j][1]) == 0)
4767                                                if (col == 3)
4768                                                        if (CoefSelWave[j][col] & 0x10)
4769                                                                CoefListWave[i][col] = " X"
4770                                                        else
4771                                                                CoefListWave[i][col] = ""
4772                                                        endif
4773                                                else
4774                                                        CoefListWave[i][col] = CoefListWave[j][col]
4775                                                endif
4776                                                break
4777                                        endif
4778                                endfor
4779                                continue                // skip incrementing coefIndex
4780                        elseif (OKtoSetLinkRows)                // indent 3
4781                                linktext = (CoefListWave[i][1])[5,strlen(CoefListWave[i][1])-1]
4782                                for (j = 0; j < nTotalCoefs; j += 1)            // indent 4
4783                                        if ( (CmpStr(linktext, CoefListWave[j][1]) == 0) || (CmpStr(CoefListWave[i][1], CoefListWave[j][1]) == 0) )             // indent 5
4784                                                // we have found the master row                                         or one of the linked rows
4785                                                if (col == 3)           // indent 6
4786                                                        if (w[coefIndex][0])
4787                                                                CoefSelWave[j][col] = 0x20 + 0x10
4788                                                        else
4789                                                                CoefSelWave[j][col] = 0x20
4790                                                        endif
4791                                                else            // indent 6
4792                                                        sprintf dumstr, formatStr, w[coefIndex][0]
4793                                                        nstr = strlen(dumstr)
4794                                                        Variable k
4795                                                        for (k = 0; k < nstr; k += 1)
4796                                                                if (char2num(dumstr[k]) != char2num(" "))
4797                                                                        break
4798                                                                endif
4799                                                        endfor
4800                                                        if (k > 0)
4801                                                                dumstr = dumstr[k, strlen(dumstr)-1]
4802                                                        endif
4803                                                        CoefListWave[j][col] = dumstr
4804                                                endif           // indent 6
4805//                                              coefIndex += 1
4806                                        endif           // indent 5
4807                                endfor          // indent 4
4808                        endif           // indent 3
4809                endif           // indent 2
4810                coefIndex += 1
4811        endfor          // indent 1
4812end
4813
4814static Function SaveCoefListToWave(w, col, SaveOnlySelectedCells, OKToSaveLinkCells)
4815        Wave w
4816        Variable col
4817        Variable SaveOnlySelectedCells
4818        Variable OKToSaveLinkCells
4819       
4820        Wave/T CoefListWave = root:Packages:NewGlobalFit:NewGF_CoefControlListWave
4821        Wave CoefSelWave = root:Packages:NewGlobalFit:NewGF_CoefControlListSelWave
4822        Variable ntotalCoefs = totalCoefsFromCoefList()
4823        Variable i
4824        Variable waveIndex = 0
4825       
4826        for (i = 0; i < ntotalCoefs; i += 1)
4827                if (OKToSaveLinkCells || !IsLinkText(CoefListWave[i][1]))
4828                        if ( SaveOnlySelectedCells && !IsRowSelected(CoefSelWave, i) )
4829                                continue
4830                        endif
4831                        if (col == 3)
4832                                w[waveIndex] = ((CoefSelWave[i][col] & 0x10) != 0)
4833                        else
4834                                w[waveIndex] = str2num(CoefListWave[i][col])
4835                        endif
4836                        waveIndex += 1
4837                endif
4838        endfor
4839end
4840
4841static Function FindSelectedRows(SelectionWave)
4842        Wave SelectionWave
4843       
4844        Variable rows = DimSize(SelectionWave, 0)
4845        Variable cols = DimSize(SelectionWave, 1)
4846        Variable i,j
4847        Variable rowsSelected = 0
4848       
4849        for (i = 0; i < rows; i += 1)
4850                for (j = 0; j < cols; j += 1)
4851                        if (IsRowSelected(SelectionWave, i))
4852                                rowsSelected += 1
4853                                break;
4854                        endif
4855                endfor
4856        endfor
4857       
4858        return rowsSelected;
4859end
4860
4861static Function IsRowSelected(SelectionWave, row)
4862        Wave SelectionWave
4863        Variable row
4864       
4865        Variable cols = DimSize(SelectionWave, 1)
4866        Variable j
4867       
4868        for (j = 0; j < cols; j += 1)
4869                if (SelectionWave[row][j] & 9)
4870                        return 1
4871                        break;
4872                endif
4873        endfor
4874       
4875        return 0;
4876end
4877
4878//SRK - new function to generate a report (always)
4879Function Generate_GF_Report(topGraph,GF_resultStr)
4880        String topGraph,GF_resultStr
4881       
4882        String nb = "GF_Report"
4883        String str=""
4884       
4885        // bring report up
4886        DoWindow/F GF_Report
4887        if (V_flag == 0)                // Report notebook doesn't exist ?
4888                NewNotebook/W=(10,45,550,620)/F=1/N=GF_Report as "Global Fit Report"
4889        endif
4890        // delete old stuff
4891        Notebook $nb selection={startOfFile, endOfFile}, text="\r", selection={startOfFile, startOfFile}
4892       
4893        //setup
4894        Notebook $nb defaultTab=36, statusWidth=252, pageMargins={44,44,44,44}          //44 points = 0.6" margin all around
4895        Notebook $nb showRuler=1, rulerUnits=1, updating={1, 60}
4896        Notebook $nb newRuler=Normal, justification=0, margins={0,0,524}, spacing={0,0,0}, tabs={}, rulerDefaults={"Geneva",10,0,(0,0,0)}
4897//     
4898        // insert title
4899        Notebook $nb newRuler=Title, justification=1, rulerDefaults={"Times", 16, 1, (0, 0, 0)}
4900        sprintf str, "Global Fit Completed %s, %s\r\r",Secs2Date(datetime, 0), time()
4901        Notebook $nb ruler=Title, text=str
4902       
4903        //the text
4904        // -- modify to put in the coefficient labels...
4905        String dataFileStr,funcStr,nameStr,paramStr,suffix,savDF
4906        Variable num,ii
4907        savDF = GetDataFolder(1)
4908        sscanf StringFromList(4,GF_ResultStr,"\r"),"Data Set:%s ; Function: %s",dataFileStr,funcStr
4909        dataFileStr = dataFileStr[0,strlen(dataFileStr)-3]              //remove the "_i"
4910        suffix = getModelSuffix(getFunctionCoef(funcStr))
4911        SetDataFolder $("root:"+dataFileStr+":")
4912        paramStr = WaveList("*param*_"+suffix, "", "TEXT:1," )
4913        Wave/T pw = $paramStr
4914        num=numpnts(pw)
4915        for(ii=0;ii<num;ii+=1)
4916                GF_resultStr = ReplaceString("Coef_"+num2str(ii), GF_resultStr, pw[ii])
4917        endfor
4918        SetDataFolder $savDF
4919       
4920        Notebook $nb ruler=Normal
4921        Notebook $nb  margins={0,0,524}, tabs={63 + 3*8192}
4922        Notebook $nb text=GF_resultStr
4923       
4924        //the graph
4925        Notebook $nb picture={$topGraph(0, 0, 400, 300), -5, 1}, text="\r"
4926       
4927        // show the top of the report
4928        Notebook $nb  selection= {startOfFile, startOfFile},  findText={"", 1}
4929       
4930        //save the notebook and the graphic file
4931//      if(yesSave)
4932//              String nameStr=CleanupName(func,0)
4933//              nameStr = nameStr[0,8]  //shorten the name
4934                nameStr = "GF_"+dataFileStr
4935                //make sure the name is no more than 31 characters
4936                namestr = namestr[0,30]         //if shorter than 31, this will NOT pad to 31 characters
4937                Print "file saved as ",nameStr
4938                SaveNotebook /O/P=home/S=2 $nb as nameStr
4939//              //save the graph separately as a PICT file, 2x screen
4940//              pictStr += nameStr
4941//              pictStr = pictStr[0,28]         //need a shorter name - why?
4942////            DoWindow/F $topGraph
4943//              // E=-5 is png @screen resolution
4944//              // E=2 is PICT @2x screen resolution
4945/////           SavePICT /E=-5/O/P=home /I/W=(0,0,3,3) as pictStr
4946//              SavePICT /E=-5/O/P=home/WIN=$topGraph /W=(0,0,400,300) as pictStr
4947//      Endif
4948       
4949        return(0)
4950end
4951
4952
Note: See TracBrowser for help on using the repository browser.