source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/Automated_SANS_Reduction.ipf @ 1133

Last change on this file since 1133 was 954, checked in by srkline, 8 years ago

converted and renamed VSANS files. "VC_" prefix for VCALC related files (that's all of them right now), and moved and renamed parts of files so that the ipf names are more logical now with the contents. Deleted the "V_" prefix files. Added a lengthy routine to be able to write out a VSANS file in HDF format. This is NOT the final and approved data format, only a working version so that I can test things out...

File size: 36.2 KB
Line 
1#pragma rtGlobals=3             // Use modern global access method and strict wave access.
2
3
4//// a bunch of test functions to try to automate data reduction
5//
6// OCT 2014
7//
8//
9//
10//
11//
12// 1) start with gathering some basic information
13//              AskForConfigurations()
14//
15// 2) then sort the configurations from low Q to high Q
16//              SortConfigs()
17//
18//
19// 3) fill in the other files for the configuration. Currently a manual operation
20//
21//
22// 4) from the matrix of file numbers and some default choices,
23// save (n) configurations as config_n, to match row (n) of the matrix
24//
25// -- panel must be open
26//              ReductionProtocolPanel()
27//              FillInProtocol(index) -- need to set the ABS parameters before saving
28//              --save the protocol (I pick the name)   
29//              Auto_SaveProtocol(index)
30//
31//      ---- Run as:
32//              Auto_FillSaveProtocols()
33//
34// 5) calculate all of the transmissions
35// -- start by opening the Transmission panel
36// -- list all of the files
37// then:
38// - for each empty beam file:
39//              setXYBox (writes out box and counts to the file)
40//              check if there are transmission measurements at this config (SDD && lam)
41//                      if so, this is the empty beam
42//                              so try to guess the scattering files and calc transmission
43//
44//                      go get another transmission at this configuration
45//
46//              go get another empty beam file
47//
48//      - at the end, search through all of the scattering files. look at
49// the S_Transmission wave for: T=1 (be sure these are blocked beam) and search for
50//  T > 1, as these are wrong.
51//
52//      -- may need user intervention if things go wrong.
53//
54//      ---- to Run:
55//              Auto_Transmission()
56// then
57//              ListFiles_TransUnity()
58//              ListFiles_TransTooLarge()
59//
60//
61//
62// 6) reduce all of the data at each configuration
63//
64// - open the MRED panel
65// - for each configuration
66// - pick the configuration
67// - get the SDD, and the list of scattering files
68// - set the list and reduce all files
69// - when saving the files, can I enforce a prefix C0_, C1_etc. on the files?
70//
71// ---- Run As:
72//    Auto_MRED()
73//
74//
75// 7) figure out how to combine the data
76//
77// -- get listings of what I think I should be combining - this is saved from the transmission assignment
78// (default trim of data points for overlap, no rescaling)
79//
80//
81// -- look for the beamstop shadow at the beginning of the file
82// -- trim a default 5? 10? from the high Q end
83//
84// -- then just concatentate and sort.
85//
86//      ---- Run As:
87//                      Auto_NSORT(tableOnly=1)          to allow editing of the list of files and names
88//                      Auto_NSORT(tableOnly=0)         does the combination
89//
90//
91///////////////////////////////////
92//
93// TODO
94//
95//
96//              --properly generate the help file (reformat), link it to the help button, and get it into the SANS reduction
97//                              help file.
98//              -- make a better entry point from the Macros menu, and the SANS menu
99//
100//              -- may want to allow for some user feedback in NSORT in selecting the exact points to keep
101//       this is still a step where human judgement is rather useful.
102//     --  make it easier to edit the NSORT table. may be helpful to see the sample labels. This was
103//      clearly the case with 4 configs (one lens) since they fell in different piles during transmission
104//      calculation, so they did not appear together for combining files.
105//
106//
107
108
109
110
111///////// A simple panel so I don't have to run the commands
112//
113// --there is nothing to initialize
114//
115
116
117Proc Auto_Reduce_Panel() : Panel
118        PauseUpdate; Silent 1           // building window...
119        NewPanel /W=(1323,334,1574,663) /K=1
120        DoWindow/C AutoReduce
121        ModifyPanel cbRGB=(26205,52428,1)
122        SetDrawLayer UserBack
123        SetDrawEnv fname= "Monaco",fstyle= 1
124        DrawText 7,28,"(1)"
125        SetDrawEnv fname= "Monaco",fstyle= 1
126        DrawText 7,68,"(2)"
127        SetDrawEnv fname= "Monaco",fstyle= 1
128        DrawText 7,108,"(3)"
129        SetDrawEnv fname= "Monaco",fstyle= 1
130        DrawText 7,148,"(4)"
131        SetDrawEnv fname= "Monaco",fstyle= 1
132        DrawText 27,174,"(4.1)"
133        SetDrawEnv fname= "Monaco",fstyle= 1
134        DrawText 27,193,"(4.2)"
135        SetDrawEnv fname= "Monaco",fstyle= 1
136        DrawText 7,228,"(5)"
137        SetDrawEnv fname= "Monaco",fstyle= 1
138        DrawText 7,269,"(6)"
139        SetDrawEnv fname= "Monaco",fstyle= 1
140        DrawText 27,295,"(6.1)"
141        SetDrawEnv fstyle= 1
142        SetDrawEnv save
143
144        Button button0,pos={35,10},size={150,20},proc=AutoAskForConfigButton,title="Ask for Config"
145        Button button1,pos={35,50},size={150,20},proc=AutoSortConfigButton,title="Fill Config"
146        Button button2,pos={35,90},size={150,20},proc=AutoFillProtocolButton,title="Fill Protocols"
147        Button button3,pos={35,130},size={150,20},proc=AutoCalcTransButton,title="Calc Transmission"
148        Button button4,pos={70,155},size={150,20},proc=AutoFindUnityTransButton,title="Unity Transm"
149        Button button5,pos={70,175},size={150,20},proc=AutoFindLargeTransButton,title="Large Transm"
150        Button button6,pos={35,210},size={150,20},proc=AutoReduceEverythingButton,title="Reduce Everything"
151        Button button7,pos={35,250},size={150,20},proc=AutoNSORTTableButton,title="NSORT Table"
152        Button button8,pos={70,275},size={150,20},proc=AutoNSORTEverythingButton,title="NSORT Everything"
153
154        Button button9,pos={220,5},size={20,20},proc=AutoReduceHelpButton,title="?"
155       
156EndMacro
157
158// make the matrix a numeric wave.
159// assume that the DIV file can be found from the file list as ".DIV"
160// and the MASK file can be found as ".MASK" (if not, ask for help)
161//
162//
163Function AskForConfigurations()
164
165        Variable num
166        Prompt num,"How many configurations were used?"
167        DoPrompt "Enter the number of configs",num
168       
169        Make/O/D/N=(num,5) Configs
170        WAVE w = Configs
171        // set the column labels
172        SetDimLabel 1,0,'SDD',w
173        SetDimLabel 1,1,'Wavelength',w
174        SetDimLabel 1,2,'BKG',w
175        SetDimLabel 1,3,'EMP',w
176        SetDimLabel 1,4,'Empty Beam',w
177
178        Edit w.ld
179        ModifyTable width(Configs.l)=20
180       
181        DoAlert 0, "Fill in the SDD and wavelength for each configuration"
182
183        return(0)
184end
185
186//
187//
188Function SortConfigs()
189
190        WAVE w = Configs
191         
192        Variable num = DimSize(w, 0 )
193
194        Make/O/D/N=(num) wave0,wave1
195        wave0 = w[p][%'SDD']
196        wave1 = w[p][%'Wavelength']
197       
198        Sort/R {wave0,wave1},wave0,wave1
199
200        w[][%'SDD'] = wave0[p]
201        w[][%'Wavelength'] = wave1[p]
202       
203        KillWaves wave0,wave1
204
205// now try to find the configurations as best as I can
206        // loop over the rows
207        Variable ii
208        for(ii=0;ii<num;ii+=1)
209                FindConfigurationFiles(ii)
210        endfor
211
212        DoAlert 0, "I've sorted Low Q to High Q -- And while at it, filled in the run numbers for BKG, EMP and empty beam for each configuration"
213
214        return(0)
215End
216
217
218//
219// find the other files for each configuration as best possible
220//
221//
222Function FindConfigurationFiles(row)
223        Variable row
224       
225        WAVE w = Configs
226
227        // for the SDD and wavelength, find the BKG and EMP and Empty beam
228        Variable sdd, lam
229        sdd = w[row][%'SDD']
230        lam = w[row][%'Wavelength']
231
232        //(see MRED and Patch for help on this)
233        // find files with a reasonable string in the header somewhere -- returns a short list
234        // filter out the wrong SDD
235        // filter out the wrong wavelength
236        // filter out (is Trans) if needed
237
238        string newList="",item,matchStr,list="",pathStr
239        Variable num,ii,runNum
240
241        PathInfo catPathName
242        pathStr = S_Path
243       
244// blocked beam
245        matchStr = "block"
246        list = FindFileContainingString(matchStr)
247
248//      print list
249        newList = ""
250        num = ItemsinList(list)
251        for(ii=0;ii<num;ii+=1)
252                item = StringFromList(ii, list)
253                if(SameSDD_byName(pathStr+item,sdd) && SameWavelength_byName(pathStr+item,lam) && !isTransFile(pathStr+item))
254                        newList += item
255                        break           //only keep the first instance
256                endif   
257        endfor
258       
259        runNum = GetRunNumFromFile(newList)
260        w[row][%'BKG'] = runNum
261       
262        Printf "Config %d BKG: %s = %s\r",row,newList,getSampleLabel(pathStr+newList)
263       
264        // and the empty cell scattering
265        matchStr = "empty"
266        list = FindFileContainingString(matchStr)
267
268//      print list
269        newList = ""
270        num = ItemsinList(list)
271        for(ii=0;ii<num;ii+=1)
272                item = StringFromList(ii, list)
273                if(SameSDD_byName(pathStr+item,sdd) && SameWavelength_byName(pathStr+item,lam) && !isTransFile(pathStr+item))
274                        newList += item
275                        break           //only keep the first instance
276                endif   
277        endfor
278       
279        runNum = GetRunNumFromFile(newList)
280        w[row][%'EMP'] = runNum
281       
282       
283        Printf "Config %d EMP: %s = %s\r",row,newList,getSampleLabel(pathStr+newList)
284
285        //and the empty beam transmission
286        matchStr = "empty"
287        list = FindFileContainingString(matchStr)
288
289//      print list
290        newList = ""
291        num = ItemsinList(list)
292        for(ii=0;ii<num;ii+=1)
293                item = StringFromList(ii, list)
294                if(SameSDD_byName(pathStr+item,sdd) && SameWavelength_byName(pathStr+item,lam) && isTransFile(pathStr+item))
295                        newList += item
296                        break           //only keep the first instance
297                endif   
298        endfor
299       
300        runNum = GetRunNumFromFile(newList)
301        w[row][%'Empty Beam'] = runNum
302
303        Printf "Config %d Empty beam: %s = %s\r\r",row,newList,getSampleLabel(pathStr+newList)
304       
305
306        return(0)
307End
308
309Function/S FindFileContainingString(matchStr)
310        string matchStr
311       
312
313        string newList,item,list=""
314        Variable num,ii
315
316       
317        newList = GetRawDataFileList()
318        num=ItemsInList(newList)
319
320        for(ii=0;ii<num;ii+=1)
321                item=StringFromList(ii, newList , ";")
322//              Grep/P=catPathName/Q/E=("(?i)\\b"+matchStr+"\\b") item
323                Grep/P=catPathName/Q/E=("(?i)"+matchStr) item
324                if( V_value )   // at least one instance was found
325                        list += item + ";"
326                endif
327        endfor
328
329        newList = list
330
331       
332        return(newList)
333end
334
335
336
337
338Function/S FindDIVFile()
339       
340        String list,fileStr=""
341       
342        list = IndexedFile(catPathName, -1, ".DIV")
343//      Print list
344//      if(itemsinlist(list) == 1)
345                fileStr = StringFromList(0, list)               // just return the first one
346//      endif
347       
348        return(fileStr)
349
350End
351
352Function/S FindMASKFile()
353
354        String list,fileStr=""
355       
356        list = IndexedFile(catPathName, -1, ".MASK")
357//      Print list
358//      if(itemsinlist(list) == 1)
359                fileStr = StringFromList(0, list)               // just return the first one
360//      endif
361       
362        return(fileStr)
363End
364
365// returns true (1) if the run number has the same SDD as input
366Function SameSDD_byRun(runNum,sdd)
367        Variable runNum,sdd
368
369        String fname
370        Variable good
371       
372        good = 0
373        fname = ""
374        //generate a name
375        fname = FindFileFromRunNumber(runNum)
376        // test
377        good = SameSDD_byName(fname,sdd)
378       
379        return(good)
380End
381
382
383// returns true (1) if the file (fullPath) has the same SDD as input
384// -- fuzzy test, within 1% is a match
385//
386Function SameSDD_byName(fname,sdd)
387        String fname
388        Variable sdd
389
390        Variable good,tmp,tolerance
391       
392        tolerance = 0.01
393        good = 0
394        tmp = getSDD(fname)
395       
396        if(abs(tmp - sdd) < tolerance)          //need a fuzzy test here, just like for the wavelength
397                return(1)
398        else
399                return(0)
400        endif
401       
402End
403
404// returns true (1) if the run number has the same wavelength as input
405Function SameWavelength_byRun(runNum,lambda)
406        Variable runNum,lambda
407
408        String fname
409        Variable good
410       
411        good = 0
412        fname = ""
413        //generate a name
414        fname = FindFileFromRunNumber(runNum)
415        // test
416        good = SameWavelength_byName(fname,lambda)
417       
418        return(good)
419End
420
421
422// returns true (1) if the file (fullPath) has the same wavelength as input
423// -- fuzzy test, within 1% is a match
424//
425Function SameWavelength_byName(fname,lambda)
426        String fname
427        Variable lambda
428
429        Variable good,tmp,tolerance
430       
431        tolerance = 0.01
432        good = 0
433        tmp = getWavelength(fname)
434       
435        if(abs(tmp - lambda) < tolerance)               //need a fuzzy test here
436                return(1)
437        else
438                return(0)
439        endif
440       
441End
442
443
444// simple loop to automate the generation/saving of protocols from the configuration matrix
445//
446Function Auto_FillSaveProtocols()
447
448        WAVE w = root:Configs
449         
450        Variable num,ii
451        num = DimSize(w,0)
452       
453        for(ii=0;ii<num;ii+=1)
454                FillInProtocol(ii)
455                Auto_SaveProtocol(ii)
456        endfor
457       
458        return(0)
459End
460
461//
462// I could possibly just fill in the protocol on my own, or
463// fill in the panel and go through the parsing.
464//
465// be sure the panel is open before starting this.
466//
467Function FillInProtocol(index)
468        variable index
469       
470        // be sure it's open and on top (redundant, but do it anyways)
471        Execute "ReductionProtocolPanel()"
472       
473        SVAR bgd = root:myGlobals:Protocols:gBGD
474        SVAR emp = root:myGlobals:Protocols:gEMP
475        SVAR div = root:myGlobals:Protocols:gDIV
476        SVAR mask = root:myGlobals:Protocols:gMASK
477        SVAR gABS = root:myGlobals:Protocols:gAbsStr
478
479        WAVE configs=root:configs
480        bgd = num2str(configs[index][%'BKG'])
481        emp = num2str(configs[index][%'EMP'])
482
483        div = FindDIVFile()
484        mask = FindMASKFile()
485       
486        // now do the absolute scaling
487        // be sure to load in the DIV file
488        String pathStr
489        PathInfo catPathName
490        pathStr = S_path
491       
492        ReadHeaderAndWork("DIV",pathStr+div)
493       
494        // be sure that the beam center is properly set
495        Auto_FindWriteBeamCenter(configs[index][%'Empty Beam'])
496       
497        // then I can calculate Kappa
498        gABS = Auto_CalcKappa(configs[index][%'Empty Beam'])
499       
500        return(0)
501end
502
503
504Function Auto_SaveProtocol(index)
505        variable index
506       
507        String newProtocol
508       
509        newProtocol = "config_"+num2str(index)
510        Make/O/T/N=8 $("root:myGlobals:Protocols:" + newProtocol)
511        MakeProtocolFromPanel( $("root:myGlobals:Protocols:" + newProtocol) )
512       
513        return(0)
514End
515
516
517
518//
519// parallels the functionality of AskForAbsoluteParams_Quest()
520//
521Function/S Auto_CalcKappa(runNum)
522        Variable runNum
523       
524        String filename,pathStr
525       
526        filename = FindFileFromRunNumber(runNum)
527       
528        ReadHeaderAndData(filename)     //this is the full Path+file
529        UpdateDisplayInformation("RAW")                 //display the new type of data that was loaded
530       
531        Wave/T tw=$"root:Packages:NIST:RAW:TextRead"
532        Wave rw=$"root:Packages:NIST:RAW:RealsRead"
533        Wave iw=$"root:Packages:NIST:RAW:IntegersRead"
534        Wave data = $"root:Packages:NIST:raw:linear_data"               //this will be the linear data
535        String acctStr = tw[3] 
536
537
538        //get the necessary variables for the calculation of kappa
539        Variable detCnt,countTime,attenTrans,monCnt,sdd,pixel,kappa
540        Variable kappa_err
541        String detStr=tw[9],junkStr,errStr
542
543        pixel = rw[10]/10                       // header value (X) is in mm, want cm here
544
545        countTime = iw[2]
546        //detCnt = rw[2]                //080802 -use sum of data, not scaler from header
547        monCnt = rw[0]
548        sdd = rw[18]
549        sdd *=100               //convert from meters to cm
550                               
551        //lookup table for transmission factor
552        //determine which instrument the measurement was done on from acctStr
553        Variable lambda = rw[26]
554        Variable attenNo = rw[3]
555        Variable atten_err
556        attenTrans = AttenuationFactor(acctStr,lambda,attenNo,atten_err)
557        //Print "attenTrans = ",attenTrans
558       
559        Variable x1,x2,y1,y2,ct_err
560        Variable xctr,yctr
561        // set the xy box to be the whole detector to find the beam center (may be wrong in the file)
562        // then +/- 20 pix (within bounds) to sum
563
564        xctr = rw[16]
565        yctr = rw[17]
566
567        x1 = xctr - 15
568        x2 = xctr + 15
569        y1 = yctr - 15
570        y2 = yctr + 15
571        KeepSelectionInBounds(x1,x2,y1,y2)
572
573        Printf "Using Box X(%d,%d),Y(%d,%d)\r",x1,x2,y1,y2
574       
575        //need the detector sensitivity file - make a guess, allow to override
576        // it must already be there, done by calling routine
577        //
578        Wave divData = $"root:Packages:NIST:div:Data"
579        // correct by detector sensitivity
580        data /= divData
581       
582        detCnt = SumCountsInBox(x1,x2,y1,y2,ct_err,"RAW")
583        if(cmpstr(tw[9],"ILL   ")==0)
584                detCnt /= 4             // for cerca detector, header is right, sum(data) is 4x too large this is usually corrected in the Add step
585                pixel *= 1.04                   // correction for true pixel size of the Cerca
586        endif
587        //             
588        kappa = detCnt/countTime/attenTrans*1.0e8/(monCnt/countTime)*(pixel/sdd)^2
589       
590        kappa_err = (ct_err/detCnt)^2 + (atten_err/attenTrans)^2
591        kappa_err = sqrt(kappa_err) * kappa
592               
593        junkStr = num2str(kappa)
594        errStr = num2Str(kappa_err)
595               
596        // set the parameters in the global string
597        Execute "AskForAbsoluteParams(1,1,"+junkStr+",1,"+errStr+")"            //no missing parameters, no dialog
598               
599        DoWindow/K SANS_Data
600
601        Printf "Kappa was successfully calculated as = %g +/- %g (%g %)\r",kappa,kappa_err,(kappa_err/kappa)*100
602       
603        SVAR kapStr = root:myGlobals:Protocols:gAbsStr 
604       
605        return(kapStr)
606end
607
608
609// given a run number:
610// -- load it to RAW
611// -- find the beam center
612// -- write this out to the file
613//
614Function Auto_FindWriteBeamCenter(runNum)
615        Variable runNum
616       
617        String filename,pathStr
618       
619        filename = FindFileFromRunNumber(runNum)
620       
621        ReadHeaderAndData(filename)     //this is the full Path+file
622        UpdateDisplayInformation("RAW")                 //display the new type of data that was loaded
623
624        Wave data = $"root:Packages:NIST:raw:linear_data"               //this will be the linear data
625
626        Variable xzsum,yzsum,zsum,ii,jj,top,bottom,left,right
627        Variable counts,xctr,yctr
628        xzsum = 0
629        yzsum = 0
630        zsum = 0
631       
632        left = 0
633        right = 127
634        bottom = 0
635        top = 127
636        // count over rectangular selection, doing each row, L-R, bottom to top
637        ii = bottom -1
638        do
639                ii +=1
640                jj = left-1
641                do
642                        jj += 1
643                        counts = data[jj][ii]
644                        xzsum += jj*counts
645                        yzsum += ii*counts
646                        zsum += counts
647                while(jj<right)
648        while(ii<top)
649       
650        xctr = xzsum/zsum
651        yctr = yzsum/zsum
652       
653        // add 1 to each to get to detector coordinates (1,128)
654        // rather than the data array which is [0,127]
655        xctr+=1
656        yctr+=1
657       
658        Print "Automatic Beam X-center (in detector coordinates) = ",xctr
659        Print "Automatic Beam Y-center (in detector coordinates) = ",yctr
660
661        //write the center to the header, so I don't need to find it again
662        WriteBeamCenterXToHeader(filename,xctr)
663        WriteBeamCenterYToHeader(filename,yctr)
664       
665        return(0)
666       
667End
668
669
670// load the file
671// - convert to SAM
672// - find the box and write out the counts
673//
674//  parallels SetXYBoxCoords()
675//
676Function Auto_SetXYBox(runNum)
677        Variable runNum
678
679        String filename,pathStr
680        Variable err,xctr,yctr,x1,x2,y1,y2
681        filename = FindFileFromRunNumber(runNum)
682
683// load the data        and convert to SAM
684        ReadHeaderAndData(filename)     //this is the full Path+file
685        UpdateDisplayInformation("RAW")                 //display the new type of data that was loaded
686        err = Raw_to_work("SAM")
687        String/G root:myGlobals:gDataDisplayType="SAM"
688        UpdateDisplayInformation("SAM")                 //display the new type of data that was loaded
689//      fRawWindowHook()
690
691// set the XYBox
692        xctr = getBeamXPos(filename)
693        yctr = getBeamYPos(filename)
694
695        x1 = xctr - 15
696        x2 = xctr + 15
697        y1 = yctr - 15
698        y2 = yctr + 15
699        KeepSelectionInBounds(x1,x2,y1,y2)
700        //write string as keyword-packed string, to use IGOR parsing functions
701        String msgStr = "X1="+num2str(x1)+";"
702        msgStr += "X2="+num2str(x2)+";"
703        msgStr += "Y1="+num2str(y1)+";"
704        msgStr += "Y2="+num2str(y2)+";"
705        String/G root:myGlobals:Patch:gPS3 = msgStr
706        String/G root:myGlobals:Patch:gEmpBox = msgStr
707        //changing this global wil update the display variable on the TransPanel
708        String/G root:myGlobals:TransHeaderInfo:gBox = msgStr
709
710// get the counts and write everything to the header
711        Variable counts,ct_err
712        counts = SumCountsInBox(x1,x2,y1,y2,ct_err,"SAM")
713       
714        WriteXYBoxToHeader(filename,x1,x2,y1,y2)
715       
716        Print counts, " counts in XY box"
717        WriteBoxCountsToHeader(filename,counts)
718       
719        WriteBoxCountsErrorToHeader(filename,ct_err)
720       
721       
722        return(0)
723End
724
725//// calculating the transmissions
726// 5) calculate all of the transmissions
727// -- start by opening the Transmission panel
728// -- list all of the files
729// then:
730// - for each empty beam file:
731//              setXYBox (write out box and counts to the file)
732//              check if there are transmission measurements at this config (SDD && lam)
733//                      if so, this is the empty beam
734//                              so try to guess the scattering files and calc transmission
735//
736//                      go get another transmission at this configuration
737//
738//              go get another empty beam file
739//
740//      - at the end, search through all of the scattering files. look at
741// the S_Transmission wave for: T=1 (be sure these are blocked beam) and search for
742//  T > 1, as these are wrong.
743//
744//      -- may need user intervention if things go wrong.
745//
746Function Auto_Transmission()
747
748        //open the panel
749        Execute "CalcTrans()"
750        //list the files - this is equivalent to pressing the button
751        Execute "BuildFileTables()"
752       
753        // get all of the empty beam files (from the initial setup)
754        WAVE configs = root:configs
755       
756        // declare all of the necessary TransTable files so that I can check, and do assignments
757        WAVE/T TransFiles = $"root:myGlobals:TransHeaderInfo:T_Filenames"
758        WAVE/T EmpAssignments = $"root:myGlobals:TransHeaderInfo:T_EMP_Filenames"
759       
760        Variable nEmpFiles,nTransFiles,ii,jj,empNum,empLam,empSDD,testNum,numChars
761        String empName="",pathStr,testName
762       
763        PathInfo catPathName
764        pathStr = S_path
765       
766        numChars = 8            //for the trans guess
767       
768        nEmpFiles = DimSize(configs, 0)
769        nTransFiles = numpnts(TransFiles)
770
771
772// this is only to save the "matches" for use later in combining the reduced data
773        SVAR gMatchSamStr = root:myGlobals:TransHeaderInfo:gMatchingSampleFiles
774        Make/O/T/N=(nTransFiles) savedMatches
775        savedMatches = ""
776
777        for(ii=0;ii<nEmpFiles;ii+=1)            //loop over the empty beam files (from Configs)
778                empNum = configs[ii][%'Empty Beam']
779                empName = GetFileNameFromPathNoSemi(FindFileFromRunNumber(empNum))
780                // auto_find the beam center
781                Auto_FindWriteBeamCenter(empNum)
782                // set the XY box for the file, and the counts in the box
783                Auto_SetXYBox(empNum)
784               
785                // get the wavelength and SDD (from the config) for comparison
786                empLam = configs[ii][%'Wavelength']
787                empSDD = configs[ii][%'SDD']
788               
789               
790                // loop through the trans files in the table (skip the empNum file)
791                // and see if any match the configuration
792                // -- if so do something
793               
794                for(jj=0;jj<nTransFiles;jj+=1)
795//              for(jj=0;jj<10;jj+=1)
796               
797                        // if it's the same file, skip it
798                        testNum = GetRunNumFromFile(TransFiles[jj])
799                        testName = TransFiles[jj]
800                        if(testNum != empNum)           
801                                // do the configurations match?
802                                if(SameWavelength_byName(pathStr+testName,empLam) && SameSDD_byName(pathStr+testName,empSDD))
803                                        // if yes:
804                                        // assign this empty beam as the reference empty beam
805                                        EmpAssignments[jj] = empName
806                                       
807                                        // try to find matching scattering runs
808                                        // set the selection on the table
809                                        ModifyTable/W=TransFileTable selection=(jj,1,jj,1,jj,1)
810                                       
811                                        // pick the number of characters to use
812                                        fGuessTransToScattFiles(numChars)
813                                       
814                                        // ** if "correct" runs are found, calculate the transmissions *** this is the tough step
815                                        // at this point, I'm still asking for user intervention, since I have no way of knowing
816                                        // how to tell if I have the right files, or even the right number of files.
817                                       
818                                        // this is a ; delimited list of the raw data files that have the same transmission assignment
819                                        // - that may be the ones to combine together.
820                                        savedMatches[jj] = gMatchSamStr                 
821                                       
822                                endif
823                        endif
824                endfor
825               
826        endfor          //loop over all empty beam files
827
828        DoAlert 0,"Transmissions are done"
829
830        return(0)
831End
832
833
834// spit out a list of scattering files with T=1
835// ask the user if these are OK
836Function ListFiles_TransUnity()
837
838        WAVE/T S_FileNames = $"root:myGlobals:TransHeaderInfo:S_FileNames"
839        WAVE/T S_Labels = $"root:myGlobals:TransHeaderInfo:S_Labels"
840        WAVE S_Transmission = $"root:myGlobals:TransHeaderInfo:S_Transmission"
841
842        Variable num,ii
843        num = numpnts(S_Transmission)
844       
845        for(ii=0;ii<num;ii+=1)
846                if(S_transmission[ii] == 1)
847                        printf "File %s = %s has T=1. Is this OK?\r",S_FileNames[ii],S_Labels[ii]
848                endif
849        endfor
850       
851        return(0)
852End
853
854
855// spit out a list of scattering files with T>1
856// let the user know that these are incorrect and need to be repaired
857
858Function ListFiles_TransTooLarge()
859
860        WAVE/T S_FileNames = $"root:myGlobals:TransHeaderInfo:S_FileNames"
861        WAVE/T S_Labels = $"root:myGlobals:TransHeaderInfo:S_Labels"
862        WAVE S_Transmission = $"root:myGlobals:TransHeaderInfo:S_Transmission"
863
864        Variable num,ii
865        num = numpnts(S_Transmission)
866       
867        for(ii=0;ii<num;ii+=1)
868                if(S_transmission[ii] > 1)
869                        printf "File %s = %s has T=1. This is NOT OK!\r",S_FileNames[ii],S_Labels[ii]
870                endif
871        endfor
872       
873        return(0)
874End
875
876
877
878
879// TOO -- rewrite this correctly, using a proper "fuzzy" match for the wavelength,
880// adding items that do not match to a growing list of "different" wavelengths to check against
881// -- use 1% tol, not 5%
882//
883// use the function "CloseEnough()"
884//
885Function HowManyWavelengths()
886       
887        Variable num
888        WAVE lam = root:myGlobals:CatVSHeaderInfo:Lambda
889       
890        Variable ii,npt,tol
891        npt = numpnts(lam)
892        tol = 1.01              // 1%
893       
894        Duplicate/O lam,tmp
895        sort tmp,tmp
896       
897        num = 1
898        Make/O/D/N=1 numLam
899        numLam[0] = tmp[0]
900       
901       
902        for(ii=1;ii<npt;ii+=1)
903                if(tmp[ii] > tol*numLam[num-1])
904                        InsertPoints num, 1, numLam
905                        numLam[num] = tmp[ii]
906                        num += 1
907                endif
908       
909        endfor
910       
911        Printf "Found %d different wavelengths\r",num
912       
913        return(num)
914End
915
916
917// somewhat tricky -- look for combinations of different
918// SDD and wavelength. -- if lenses are used, often they are both at the
919// same SDD, but at different wavelengths -- for lenses
920Function HowManyConfigurations()
921
922        Variable num
923        WAVE SDD = root:myGlobals:CatVSHeaderInfo:SDD
924        WAVE lam = root:myGlobals:CatVSHeaderInfo:Lambda
925       
926
927       
928        return(num)
929End
930
931
932/////
933//
934//
935Function Auto_MRED()
936
937        // open the panel
938        Execute "ReduceMultipleFiles()"
939       
940        WAVE w = root:Configs
941        SVAR protoList = root:myGlobals:MRED:gMRProtoList
942       
943        Variable num,ii,sdd,item
944        String str
945        num = DimSize(w,0)
946       
947        // protocols are named "config_n"
948        for(ii=0;ii<num;ii+=1)
949       
950                // pick the configuration (ii)
951                // set the protocol - find which list item
952                str = "config_"+num2str(ii)
953                item = WhichListItem(str, protoList)
954                PopupMenu MRProto_pop,win=Multiple_Reduce_Panel,mode=(item+1)           //popup counts from one
955
956                // get the SDD
957                SDD = w[ii][%'SDD']
958               
959                // get the scattering files at the SDD
960                Execute "CreateScatteringAtSDDTable("+num2str(SDD)+")"
961               
962                RemoveWrongLamFromSDDList(w[ii][%'Wavelength'])
963               
964                // set the list
965                AcceptMREDList("")
966               
967                // reduce them all
968                ReduceAllPopupFiles("")
969        endfor
970       
971        return(0)
972End
973
974// need fuzzy comparison
975//
976// Only wavelengths matching testLam are kept
977//
978Function RemoveWrongLamFromSDDList(testLam)
979        Variable testLam
980       
981        Wave/T filenames = $"root:myGlobals:MRED:Filenames"
982        Wave/T suffix = $"root:myGlobals:MRED:Suffix"
983        Wave/T labels = $"root:myGlobals:MRED:Labels"
984        Wave sdd = $"root:myGlobals:MRED:SDD"
985        Wave runnum = $"root:myGlobals:MRED:RunNumber"
986        Wave isTrans = $"root:myGlobals:MRED:IsTrans"
987       
988        String path
989        PathInfo catPathName
990        path = S_Path
991       
992        Variable num=numpnts(sdd),ii,tol = 0.1,lam
993       
994        ii=num-1
995        do
996                lam = getWavelength(path+filenames[ii])
997                if(trunc(abs(lam - testLam)) > tol)             //just get the integer portion of the difference - very coarse comparison
998                        DeletePoints ii, 1, filenames,suffix,labels,sdd,runnum,isTrans
999                endif
1000                ii-=1
1001        while(ii>=0)
1002       
1003        // now sort
1004        Sort RunNum,    filenames,suffix,labels,sdd,runnum,isTrans
1005        return(0)
1006End
1007
1008// does no scaling, only the basic (default) trim of the ends, concatenate, sort, and save
1009//
1010//
1011Function Auto_NSORT(tableOnly)
1012        variable tableOnly
1013
1014        Wave/T SavedMatches = root:savedMatches
1015
1016        if(tableOnly)
1017                Duplicate/T/O savedMatches saveName
1018                saveName = ""
1019        Endif
1020       
1021       
1022        DoWindow/F Auto_NSORT_Table
1023        if(V_flag == 0)
1024                Edit/N=Auto_NSORT_Table savedMatches,saveName
1025        endif
1026       
1027        Variable num,ii,numitems,numChars,jj,nEnd
1028        String item,path,tmpStr,cmd,folderStr
1029       
1030        // number of characters in the file label to keep for the file name
1031        numChars = 16
1032        // number of points to trim from end
1033        nEnd = 10
1034       
1035       
1036        PathInfo catPathName
1037        path = S_Path
1038       
1039        if(tableOnly)   
1040                num=numpnts(savedMatches)
1041        // guess at the file names
1042                for(ii=0;ii<num;ii+=1)
1043                        item = StringFromList(0, savedMatches[ii])
1044                        if(cmpstr(item,"") != 0)
1045                                tmpStr = RemoveAllSpaces(getSampleLabel(path+item))
1046                                tmpStr = CleanupName(tmpStr, 0 )
1047                                saveName[ii] = tmpStr[0,numChars-1]+".abs"
1048                        endif
1049                endfor
1050               
1051                DoAlert 0,"Edit the table to combine the correct files, and names that you like"
1052               
1053                return(0)
1054        endif
1055
1056
1057        // now, the table may have been edited
1058        num=numpnts(savedMatches)
1059
1060// now loop over the files:
1061        for(ii=0;ii<num;ii+=1)
1062                numItems = ItemsInList(savedMatches[ii])
1063                if(numItems != 0)
1064                        for(jj=0;jj<numItems;jj+=1)
1065                                // load
1066                                item = StringFromList(jj, savedMatches[ii])
1067                                folderStr = GetPrefixAndNumStrFromFile(item)            //this is where the data will be loaded to
1068                               
1069                                // check for existence first - this bypasses cases like the empty cell, which have transmission but are not reduced
1070                                if(cmpstr("",ValidFileString(folderStr+".ABS")) !=0)
1071       
1072                                        sprintf cmd , "A_LoadOneDDataToName(\"%s\",\"%s\",%d,%d)",path+folderStr+".ABS","",0,1
1073                                        Execute cmd             //no plot, force overwrite
1074                                       
1075                                        // trim
1076                                        Auto_TrimData(folderStr+"_ABS",nEnd)
1077                                        SetDataFolder root:
1078                                       
1079                                        // if first file, duplicate for a placeholder for the combined data, force overwrite
1080                                        if(jj==0)
1081                                                DuplicateDataSet(folderStr+"_ABS", CleanupName(saveName[ii],0), 1)
1082                                        else
1083                                                Auto_Concatenate(folderStr+"_ABS", CleanupName(saveName[ii],0))
1084                                        endif
1085                                       
1086                                endif
1087                        endfor
1088                       
1089                        // sort
1090                        Auto_Sort(CleanupName(saveName[ii],0))
1091                       
1092                        // save
1093                        if(DataFolderExists("root:"+CleanupName(saveName[ii],0)))
1094                                Auto_Write1DData(CleanupName(saveName[ii],0),"tab","CRLF")
1095                        endif
1096                endif
1097        endfor
1098
1099        // kill the loaded data sets (since they have been modified!)
1100        Execute "A_PlotManager_KillAll(\"\")"
1101
1102        return(0)
1103End
1104
1105
1106// this will bypass save dialogs
1107// -- AND WILL OVERWITE DATA WITH THE SAME NAME
1108//
1109Function Auto_Write1DData(folderStr,delim,term)
1110        String folderStr,delim,term
1111       
1112        String formatStr="",fullpath=""
1113        Variable refnum,dialog=1
1114       
1115        String dataSetFolderParent,basestr
1116       
1117        //Abuse ParseFilePath to get path without folder name
1118        dataSetFolderParent = ParseFilePath(1,folderStr,":",1,0)
1119        //Abuse ParseFilePath to get basestr
1120        basestr = ParseFilePath(0,folderStr,":",1,0)
1121       
1122        //make sure the waves exist
1123        SetDataFolder $(dataSetFolderParent+basestr)
1124        WAVE/Z qw = $(baseStr+"_q")
1125        WAVE/Z iw = $(baseStr+"_i")
1126        WAVE/Z sw = $(baseStr+"_s")
1127        WAVE/Z resw = $(baseStr+"_res")
1128       
1129        if(WaveExists(qw) == 0)
1130                Abort "q is missing"
1131        endif
1132        if(WaveExists(iw) == 0)
1133                Abort "i is missing"
1134        endif
1135        if(WaveExists(sw) == 0)
1136                Abort "s is missing"
1137        endif
1138        if(WaveExists(resw) == 0)
1139                Abort "Resolution information is missing."
1140        endif
1141       
1142        Duplicate/O qw qbar,sigQ,fs
1143        if(dimsize(resW,1) > 4)
1144                //it's USANS put -dQv back in the last 3 columns
1145                NVAR/Z dQv = USANS_dQv
1146                if(NVAR_Exists(dQv) == 0)
1147                        SetDataFolder root:
1148                        Abort "It's USANS data, and I don't know what the slit height is."
1149                endif
1150                sigQ = -dQv
1151                qbar = -dQv
1152                fs = -dQv
1153        else
1154                //it's SANS
1155                sigQ = resw[p][0]
1156                qbar = resw[p][1]
1157                fs = resw[p][2]
1158        endif
1159       
1160        PathInfo catPathName
1161        fullPath = S_Path + folderStr
1162
1163        Open refnum as fullpath
1164
1165        fprintf refnum,"Combined data written from folder %s on %s\r\n",folderStr,(date()+" "+time())
1166        formatStr = "%15.4g %15.4g %15.4g %15.4g %15.4g %15.4g\r\n"     
1167        fprintf refnum, "The 6 columns are | Q (1/A) | I(Q) (1/cm) | std. dev. I(Q) (1/cm) | sigmaQ | meanQ | ShadowFactor|\r\n"       
1168
1169        wfprintf refnum,formatStr,qw,iw,sw,sigQ,qbar,fs
1170        Close refnum
1171       
1172        KillWaves/Z sigQ,qbar,fs
1173       
1174        SetDataFolder root:
1175        return(0)
1176End
1177
1178
1179// concatentate folder1 to the end of folder2
1180//
1181// this seems like a lot of extra work to do something so simple...
1182//
1183Function Auto_Concatenate(folder1,folder2)
1184        String folder1,folder2
1185       
1186       
1187        Concatenate/NP {$("root:"+folder1+":"+folder1+"_q"),$("root:"+folder2+":"+folder2+"_q")},tmp_q
1188        Concatenate/NP {$("root:"+folder1+":"+folder1+"_i"),$("root:"+folder2+":"+folder2+"_i")},tmp_i
1189        Concatenate/NP {$("root:"+folder1+":"+folder1+"_s"),$("root:"+folder2+":"+folder2+"_s")},tmp_s
1190        Concatenate/NP {$("root:"+folder1+":res0"),$("root:"+folder2+":res0")},tmp_res0
1191        Concatenate/NP {$("root:"+folder1+":res1"),$("root:"+folder2+":res1")},tmp_res1
1192        Concatenate/NP {$("root:"+folder1+":res2"),$("root:"+folder2+":res2")},tmp_res2
1193        Concatenate/NP {$("root:"+folder1+":res3"),$("root:"+folder2+":res3")},tmp_res3
1194       
1195// move the concatenated result into the destination folder (killing the old stuff first)
1196        KillWaves/Z $("root:"+folder2+":"+folder2+"_q")
1197        KillWaves/Z $("root:"+folder2+":"+folder2+"_i")
1198        KillWaves/Z $("root:"+folder2+":"+folder2+"_s")
1199        KillWaves/Z $("root:"+folder2+":res0")
1200        KillWaves/Z $("root:"+folder2+":res1")
1201        KillWaves/Z $("root:"+folder2+":res2")
1202        KillWaves/Z $("root:"+folder2+":res3")
1203       
1204        Duplicate/O tmp_q $("root:"+folder2+":"+folder2+"_q")
1205        Duplicate/O tmp_i $("root:"+folder2+":"+folder2+"_i")
1206        Duplicate/O tmp_s $("root:"+folder2+":"+folder2+"_s")
1207        Duplicate/O tmp_res0 $("root:"+folder2+":res0")
1208        Duplicate/O tmp_res1 $("root:"+folder2+":res1")
1209        Duplicate/O tmp_res2 $("root:"+folder2+":res2")
1210        Duplicate/O tmp_res3 $("root:"+folder2+":res3")
1211
1212        KillWaves/Z tmp_q,tmp_i,tmp_s,tmp_res0,tmp_res1,tmp_res2,tmp_res3       
1213       
1214       
1215        return(0)               
1216End
1217                       
1218Function Auto_Sort(folderStr)
1219        String folderStr
1220
1221        if(DataFolderExists("root:"+folderStr)  == 0)
1222                return(0)
1223        endif
1224       
1225        SetDataFolder $("root:"+folderStr)
1226       
1227        Wave qw = $(folderStr + "_q")
1228        Wave iw = $(folderStr + "_i")
1229        Wave sw = $(folderStr + "_s")
1230       
1231        Wave res0 = res0
1232        Wave res1 = res1
1233        Wave res2 = res2
1234        Wave res3 = res3
1235        // sort the waves
1236       
1237        Sort qw, qw,iw,sw,res0,res1,res2,res3
1238       
1239        // restore the res wave
1240        KillWaves/Z $(folderStr+"_res")
1241        Make/O/D/N=(numpnts(qw),4) $(folderStr+"_res")
1242        WAVE resWave = $(folderStr+"_res")
1243       
1244        //Put resolution contents back
1245        reswave[][0] = res0[p]
1246        reswave[][1] = res1[p]
1247        reswave[][2] = res2[p]
1248        reswave[][3] = res3[p]
1249       
1250        SetDataFolder root:
1251        return(0)
1252End
1253                       
1254// trims the beamstop out (based on shadow)
1255// trims num from the highQ end
1256// splits the res wave into individual waves in anticipation of concatenation
1257//
1258Function Auto_TrimData(folderStr,nEnd)
1259        String folderStr
1260        Variable nEnd
1261
1262        if(DataFolderExists("root:"+folderStr)  == 0)
1263                return(0)
1264        endif
1265               
1266        SetDataFolder $("root:"+folderStr)
1267       
1268        Wave qw = $(folderStr + "_q")
1269        Wave iw = $(folderStr + "_i")
1270        Wave sw = $(folderStr + "_s")
1271        Wave res = $(folderStr + "_res")
1272       
1273        variable num,ii
1274       
1275        num=numpnts(qw)
1276        //Break out resolution wave into separate waves
1277        Make/O/D/N=(num) res0 = res[p][0]               // sigQ
1278        Make/O/D/N=(num) res1 = res[p][1]               // qBar
1279        Make/O/D/N=(num) res2 = res[p][2]               // fshad
1280        Make/O/D/N=(num) res3 = res[p][3]               // qvals
1281       
1282        // trim off the last nEnd points from everything
1283        DeletePoints num-nEnd,nEnd, qw,iw,sw,res0,res1,res2,res3
1284       
1285        // delete all points where the shadow is < 0.98
1286        num=numpnts(qw)
1287        for(ii=0;ii<num;ii+=1)
1288                if(res2[ii] < 0.98)
1289                        DeletePoints ii,1, qw,iw,sw,res0,res1,res2,res3
1290                        num -= 1
1291                        ii -= 1
1292                endif
1293        endfor
1294       
1295////Put resolution contents back???
1296//              reswave[][0] = res0[p]
1297//              reswave[][1] = res1[p]
1298//              reswave[][2] = res2[p]
1299//              reswave[][3] = res3[p]
1300//             
1301                       
1302        SetDataFolder root:
1303        return(0)
1304end
1305
1306
1307//given a filename of a SANS data filename of the form
1308//TTTTTnnn.SAn_TTT_Txxx
1309//returns the prefix "TTTTTnnn" as some number of characters
1310//returns "" as an invalid file prefix
1311//
1312// NCNR-specifc, does not really belong here - but it's a beta procedure used for automation
1313//
1314Function/S GetPrefixAndNumStrFromFile(item)
1315        String item
1316        String invalid = ""     //"" is not a valid run prefix, since it's text
1317        Variable num=-1
1318       
1319        //find the "dot"
1320        String runStr=""
1321        Variable pos = strsearch(item,".",0)
1322        if(pos == -1)
1323                //"dot" not found
1324                return (invalid)
1325        else
1326                runStr = item[0,pos-1]
1327                return (runStr)
1328        Endif
1329End
1330
1331
1332//             
1333Function AutoReduceHelpButton(ba) : ButtonControl
1334        STRUCT WMButtonAction &ba
1335
1336        switch( ba.eventCode )
1337                case 2: // mouse up
1338                        // click code here
1339                        DisplayHelpTopic/Z/K=1 "Automated SANS Data Reduction"
1340                        if(V_flag !=0)
1341                                DoAlert 0,"The SANS Reduction Automation Help file could not be found"
1342                        endif
1343                        break
1344                case -1: // control being killed
1345                        break
1346        endswitch
1347
1348        return 0
1349End
1350
1351//             
1352Function AutoAskForConfigButton(ba) : ButtonControl
1353        STRUCT WMButtonAction &ba
1354
1355        switch( ba.eventCode )
1356                case 2: // mouse up
1357                        // click code here
1358                        AskForConfigurations()
1359                        break
1360                case -1: // control being killed
1361                        break
1362        endswitch
1363
1364        return 0
1365End
1366
1367
1368Function AutoSortConfigButton(ba) : ButtonControl
1369        STRUCT WMButtonAction &ba
1370
1371        switch( ba.eventCode )
1372                case 2: // mouse up
1373                        // click code here
1374                        SortConfigs()
1375                        break
1376                case -1: // control being killed
1377                        break
1378        endswitch
1379
1380        return 0
1381End
1382
1383
1384Function AutoFillProtocolButton(ba) : ButtonControl
1385        STRUCT WMButtonAction &ba
1386
1387        switch( ba.eventCode )
1388                case 2: // mouse up
1389                        // click code here
1390                        Auto_FillSaveProtocols()
1391                        break
1392                case -1: // control being killed
1393                        break
1394        endswitch
1395
1396        return 0
1397End
1398
1399
1400Function AutoCalcTransButton(ba) : ButtonControl
1401        STRUCT WMButtonAction &ba
1402
1403        switch( ba.eventCode )
1404                case 2: // mouse up
1405                        // click code here
1406                        Auto_Transmission()
1407                        break
1408                case -1: // control being killed
1409                        break
1410        endswitch
1411
1412        return 0
1413End
1414
1415
1416Function AutoFindUnityTransButton(ba) : ButtonControl
1417        STRUCT WMButtonAction &ba
1418
1419        switch( ba.eventCode )
1420                case 2: // mouse up
1421                        // click code here
1422                        ListFiles_TransUnity()
1423                        break
1424                case -1: // control being killed
1425                        break
1426        endswitch
1427
1428        return 0
1429End
1430
1431
1432Function AutoFindLargeTransButton(ba) : ButtonControl
1433        STRUCT WMButtonAction &ba
1434
1435        switch( ba.eventCode )
1436                case 2: // mouse up
1437                        // click code here
1438                        ListFiles_TransTooLarge()
1439                        break
1440                case -1: // control being killed
1441                        break
1442        endswitch
1443
1444        return 0
1445End
1446
1447
1448Function AutoReduceEverythingButton(ba) : ButtonControl
1449        STRUCT WMButtonAction &ba
1450
1451        switch( ba.eventCode )
1452                case 2: // mouse up
1453                        // click code here
1454                        Auto_MRED()
1455                        break
1456                case -1: // control being killed
1457                        break
1458        endswitch
1459
1460        return 0
1461End
1462
1463
1464Function AutoNSORTTableButton(ba) : ButtonControl
1465        STRUCT WMButtonAction &ba
1466
1467        switch( ba.eventCode )
1468                case 2: // mouse up
1469                        // click code here
1470                        Variable tableOnly = 1
1471                        Auto_NSORT(tableOnly)
1472                        break
1473                case -1: // control being killed
1474                        break
1475        endswitch
1476
1477        return 0
1478End
1479
1480Function AutoNSORTEverythingButton(ba) : ButtonControl
1481        STRUCT WMButtonAction &ba
1482
1483        switch( ba.eventCode )
1484                case 2: // mouse up
1485                        // click code here
1486                        Variable tableOnly = 0
1487                        Auto_NSORT(tableOnly)
1488                        DoAlert 0,"Sorting and Saving Done"
1489                        break
1490                case -1: // control being killed
1491                        break
1492        endswitch
1493
1494        return 0
1495End
1496
1497
1498
1499
Note: See TracBrowser for help on using the repository browser.