source: sans/SANSReduction/branches/kline_29MAR07/Put in User Procedures/SANS_Reduction_v5.00/WorkFileUtils.ipf @ 72

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

more transferring of functions to NCNR_* files.

File size: 38.6 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma version=5.0
3#pragma IgorVersion=4.0
4
5//*******************
6// Vers 1.2 100901
7//
8//*******************
9// Utility procedures for handling of workfiles (each is housed in a separate datafolder)
10//
11// - adding data to a workfile
12// - copying workfiles to another folder
13//
14// - absolute scaling
15// - DIV detector sensitivity corrections
16//
17// - the WorkFile Math panel for simple image math
18// -
19// - adding work.drk data without normalizing to monitor counts
20//***************************
21
22
23//testing procedure, not called anymore
24Proc Add_to_Workfile(type, add)
25        String type,add
26        Prompt type,"WORK data type",popup,"SAM;EMP;BGD"
27        Prompt add,"Add to current WORK contents?",popup,"No;Yes"
28       
29        //macro will take whatever is in RAW folder and "ADD" it to the folder specified
30        //in the popup menu
31       
32        //"add" = yes/no, don't add to previous runs
33        //switch here - two separate functions to avoid (my) confusion
34        Variable err
35        if(cmpstr(add,"No")==0)
36                //don't add to prev work contents, copy RAW contents to work and convert
37                err = Raw_to_work(type)
38        else
39                //yes, add RAW to the current work folder contents
40                err = Add_raw_to_work(type)
41        endif
42       
43        String newTitle = "WORK_"+type
44        DoWindow/F SANS_Data
45        DoWindow/T SANS_Data, newTitle
46        KillStrings/Z newTitle
47       
48        //need to update the display with "data" from the correct dataFolder
49        fRawWindowHook()
50       
51End
52
53//will "ADD" the current contents of the RAW folder to the newType work folder
54//and will ADD the RAW contents to the existing content of the newType folder
55// - used when adding multiple runs together
56//(the function Raw_to_work(type) makes a fresh workfile)
57//
58//the current display type is updated to newType (global)
59Function Add_raw_to_work(newType)
60        String newType
61               
62        String destPath=""
63       
64        // if the desired workfile doesn't exist, let the user know, and just make a new one
65        destPath = "root:"+newType + ":data"
66        if(WaveExists($destpath) == 0)
67                Print "There is no old work file to add to - a new one will be created"
68                //call Raw_to_work(), then return from this function
69                Raw_to_Work(newType)
70                Return(0)               //does not generate an error - a single file was converted to work.newtype
71        Endif
72       
73        //now make references to data in newType folder
74        DestPath="root:"+newType       
75        WAVE data=$(destPath +":data")                  // these wave references point to the EXISTING work data
76        WAVE/T textread=$(destPath + ":textread")
77        WAVE integersread=$(destPath + ":integersread")
78        WAVE realsread=$(destPath + ":realsread")
79       
80        Variable deadTime,defmon,total_mon,total_det,total_trn,total_numruns,total_rtime
81        Variable ii,jj,itim,cntrate,dscale,scale,uscale,wrk_beamx,wrk_beamy,xshift,yshift
82
83// 08/01 detector constants are now returned from a function, based on the detector type and beamline
84//      dt_ornl = 3.4e-6                //deadtime of Ordella detectors as of 30-AUG-99
85//      dt_ill=3.0e-6                   //Cerca detector deadtime constant as of 30-AUG-99
86
87        defmon=1e8                      //default monitor counts
88       
89        //Yes, add to previous run(s) in work, that does exist
90        //use the actual monitor count run.savmon rather than the normalized monitor count
91        //in run.moncnt and unscale the work data
92       
93        total_mon = realsread[1]        //saved monitor count
94        uscale = total_mon/defmon               //unscaling factor
95        total_det = uscale*realsread[2]         //unscaled detector count
96        total_trn = uscale*realsread[39]        //unscaled trans det count
97        total_numruns = integersread[3] //number of runs in workfile
98        total_rtime = integersread[2]           //total counting time in workfile
99        //retrieve workfile beamcenter
100        wrk_beamx = realsread[16]
101        wrk_beamy = realsread[17]
102        //unscale the workfile data in "newType"
103        //
104        //check for log-scaling and adjust if necessary
105        ConvertFolderToLinearScale(newType)
106        //
107        //then unscale the data array
108        data *= uscale
109       
110        //DetCorr() has not been applied to the data in RAW , do it now in a local reference to the raw data
111        WAVE raw_data = $"root:RAW:data"
112        WAVE raw_reals =  $"root:RAW:realsread"
113        WAVE/T raw_text = $"root:RAW:textread"
114        WAVE raw_ints = $"root:RAW:integersread"
115       
116        //check for log-scaling of the raw data - make sure it's linear
117        ConvertFolderToLinearScale("RAW")
118       
119        DetCorr(raw_data,raw_reals)     //applies correction to raw_data, and overwrites it
120       
121        //if RAW data is ILL type detector, correct raw_data for same counts being written to 4 pixels
122        if(cmpstr(raw_text[9], "ILL   ") == 0 )         //text field in header is 6 characters "ILL---"
123                raw_data /= 4
124        endif
125       
126        //deadtime corrections to raw data
127        deadTime = DetectorDeadtime(raw_text[3],raw_text[9])            //pick the correct detector deadtime
128        itim = raw_ints[2]
129        cntrate = sum(raw_data,-inf,inf)/itim           //080802 use data sum, rather than scaler value
130        dscale = 1/(1-deadTime*cntrate)
131
132        //update totals by adding RAW values to the local ones (write to work header at end of function)
133        total_mon += raw_reals[0]
134        total_det += dscale*raw_reals[2]
135        total_trn += raw_reals[39]
136        total_rtime += raw_ints[2]
137        total_numruns +=1
138       
139        //do the beamcenter shifting if there is a mismatch
140        //and then add the two data sets together, changing "data" since it is the workfile data
141        xshift = raw_reals[16] - wrk_beamx
142        yshift = raw_reals[17] - wrk_beamy
143       
144        If((xshift != 0) || (yshift != 0))
145                DoAlert 1,"Do you want to ignore the beam center mismatch?"
146                if(V_flag==1)
147                        xshift=0
148                        yshift=0
149                endif
150        endif
151       
152        NVAR pixelsX = root:myGlobals:gNPixelsX
153        NVAR pixelsY = root:myGlobals:gNPixelsY
154       
155        If((xshift == 0) && (yshift == 0))              //no shift, just add them
156                data += dscale*raw_data         //do the deadtime correction on RAW here
157        else
158                //shift the beamcenter, then add
159                Make/O/N=1 $(destPath + ":noadd")               //needed to get noadd condition back from ShiftSum()
160                WAVE noadd = $(destPath + ":noadd")
161                Variable sh_sum                 //returned value
162                Print "BEAM CENTER MISMATCH - - BEAM CENTER WILL BE SHIFTED TO THIS FILE'S VALUE"
163                //ii,jj are just indices here, not physical locations - so [0,127] is fine
164                ii=0
165                do
166                        jj=0
167                        do
168                                //get the contribution of shifted data
169                                sh_sum = ShiftSum(data,ii,jj,xshift,yshift,noadd)
170                                if(noadd[0])
171                                        //don't do anything to data[][]
172                                else
173                                        //add the raw_data + shifted sum (and do the deadtime correction on both)
174                                        data[ii][jj] += dscale*(raw_data[ii][jj]+sh_sum)                //do the deadtime correction on RAW here
175                                Endif
176                                jj+=1
177                        while(jj<pixelsY)
178                        ii+=1
179                while(ii<pixelsX)
180        Endif
181       
182        //scale the data to the default montor counts
183        scale = defmon/total_mon
184        data *= scale
185       
186        //all is done, except for the bookkeeping of updating the header info in the work folder
187        textread[1] = date() + " " + time()             //date + time stamp
188        integersread[3] = total_numruns                                         //numruns = more than one
189        realsread[1] = total_mon                        //save the true monitor count
190        realsread[0] = defmon                                   //monitor ct = defmon
191        integersread[2] = total_rtime                   // total counting time
192        realsread[2] = scale*total_det                  //scaled detector counts
193        realsread[39] = scale*total_trn                 //scaled transmission counts
194       
195        //Add the added raw filename to the list of files in the workfile
196        String newfile = ";" + raw_text[0]
197        SVAR oldList = $(destPath + ":fileList")
198        String/G $(destPath + ":fileList") = oldList + newfile
199       
200        //reset the current displaytype to "newtype"
201        String/G root:myGlobals:gDataDisplayType=newType
202       
203        //return to root folder (redundant)
204        SetDataFolder root:
205       
206        Return(0)
207End
208
209//will copy the current contents of the RAW folder to the newType work folder
210//and do the geometric corrections and normalization to monitor counts
211//(the function Add_Raw_to_work(type) adds multiple runs together)
212//
213//the current display type is updated to newType (global)
214//
215Function Raw_to_work(newType)
216        String newType
217       
218        Variable deadTime,defmon,total_mon,total_det,total_trn,total_numruns,total_rtime
219        Variable ii,jj,itim,cntrate,dscale,scale,uscale,wrk_beamx,wrk_beamy
220        String destPath
221       
222// 08/01 detector constants are now returned from a function, based on the detector type and beamline
223//      dt_ornl = 3.4e-6                //deadtime of Ordella detectors as of 30-AUG-99
224//      dt_ill=3.0e-6                   //Cerca detector deadtime constant as of 30-AUG-99
225        defmon=1e8                      //default monitor counts
226       
227        //initialize values before normalization
228        total_mon=0
229        total_det=0
230        total_trn=0
231        total_numruns=0
232        total_rtime=0
233       
234        //Not adding multiple runs, so wipe out the old contents of the work folder and
235        // replace with the contents of raw
236
237        destPath = "root:" + newType
238       
239        //check for log-scaling of the RAW data and adjust if necessary
240        ConvertFolderToLinearScale("RAW")
241        //then continue
242
243        //copy from current dir (RAW) to work, defined by destpath
244        DestPath = "root:"+newType
245        Duplicate/O $"root:RAW:data",$(destPath + ":data")
246//      Duplicate/O $"root:RAW:vlegend",$(destPath + ":vlegend")
247        Duplicate/O $"root:RAW:textread",$(destPath + ":textread")
248        Duplicate/O $"root:RAW:integersread",$(destPath + ":integersread")
249        Duplicate/O $"root:RAW:realsread",$(destPath + ":realsread")
250        Variable/G $(destPath + ":gIsLogscale")=0                       //overwite flag in newType folder, data converted (above) to linear scale
251       
252        WAVE data=$(destPath + ":data")                         // these wave references point to the data in work
253        WAVE/T textread=$(destPath + ":textread")                       //that are to be directly operated on
254        WAVE integersread=$(destPath + ":integersread")
255        WAVE realsread=$(destPath + ":realsread")
256        String/G $(destPath + ":fileList") = textread[0]                        //a list of names of the files in the work file (1)
257       
258        //apply nonlinear, Jacobian corrections ---
259        DetCorr(data,realsread)         //the parameters are waves, and will be changed by the function
260       
261        //if ILL type detector, correct for same counts being written to 4 pixels
262        if(cmpstr(textread[9], "ILL   ") == 0 )         //text field in header is 6 characters "ILL---"
263                data /= 4
264        endif
265       
266        //deadtime corrections
267        itim = integersread[2]
268        cntrate = sum(data,-inf,inf)/itim               //use sum of detector counts rather than scaler value
269        deadtime = DetectorDeadtime(textread[3],textread[9])    //pick the correct deadtime
270        dscale = 1/(1-deadTime*cntrate)
271       
272        //update totals to put in the work header (at the end of the function)
273        total_mon += realsread[0]
274        total_det += dscale*realsread[2]
275        total_trn += realsread[39]
276        total_rtime += integersread[2]
277        total_numruns +=1
278       
279        // NO xcenter,ycenter shifting is done - this is the first (and only) file in the work folder
280       
281        //only ONE data file- no addition of multiple runs in this function, so data is
282        //just simply corrected for deadtime.
283        data *= dscale          //deadtime correction
284       
285        //scale the data to the default montor counts
286        scale = defmon/total_mon
287        data *= scale
288       
289        //all is done, except for the bookkeeping, updating the header information in the work folder
290        textread[1] = date() + " " + time()             //date + time stamp
291        integersread[3] = total_numruns                                         //numruns = 1
292        realsread[1] = total_mon                        //save the true monitor count
293        realsread[0] = defmon                                   //monitor ct = defmon
294        integersread[2] = total_rtime                   // total counting time
295        realsread[2] = scale*total_det                  //scaled detector counts
296        realsread[39] = scale*total_trn                 //scaled transmission counts
297       
298        //reset the current displaytype to "newtype"
299        String/G root:myGlobals:gDataDisplayType=newType
300       
301        //return to root folder (redundant)
302        SetDataFolder root:
303       
304        Return(0)
305End
306
307//used for adding DRK (beam shutter CLOSED) data to a workfile
308//force the monitor count to 1, since it's irrelevant
309// run data through normal "add" step, then unscale default monitor counts
310//to get the data back on a simple time basis
311//
312Function Raw_to_Work_NoNorm(type)
313        String type
314       
315        WAVE reals=$("root:RAW:realsread")
316        reals[1]=1              //true monitor counts, still in raw
317        Raw_to_work(type)
318        //data is now in "type" folder
319        WAVE data=$("root:"+type+":data")
320        WAVE new_reals=$("root:"+type+":realsread")
321       
322        Variable norm_mon,tot_mon,scale
323       
324        norm_mon = new_reals[0]         //should be 1e8
325        tot_mon = new_reals[1]          //should be 1
326        scale= norm_mon/tot_mon
327       
328        data /= scale           //unscale the data
329       
330        return(0)
331End
332
333//used for adding DRK (beam shutter CLOSED) data to a workfile
334//force the monitor count to 1, since it's irrelevant
335// run data through normal "add" step, then unscale default monitor counts
336//to get the data back on a simple time basis
337//
338Function Add_Raw_to_Work_NoNorm(type)
339        String type
340       
341        WAVE reals=$("root:RAW:realsread")
342        reals[1]=1              //true monitor counts, still in raw
343        Add_Raw_to_work(type)
344        //data is now in "type" folder
345        WAVE data=$("root:"+type+":data")
346        WAVE new_reals=$("root:"+type+":realsread")
347       
348        Variable norm_mon,tot_mon,scale
349       
350        norm_mon = new_reals[0]         //should be 1e8
351        tot_mon = new_reals[1]          //should be equal to the number of runs (1 count per run)
352        scale= norm_mon/tot_mon
353       
354        data /= scale           //unscale the data
355       
356        return(0)
357End
358
359//performs solid angle and non-linear detector corrections to raw data as it is "added" to a work folder
360//function is called by Raw_to_work() and Add_raw_to_work() functions
361//works on the actual data array, assumes that is is already on LINEAR scale
362//
363Function DetCorr(data,realsread)
364        Wave data,realsread
365       
366        Variable xcenter,ycenter,x0,y0,sx,sx3,sy,sy3,xx0,yy0
367        Variable ii,jj,dtdist,dtdis2
368        Variable xi,xd,yd,rad,ratio,domega,xy
369       
370//      Print "...doing jacobian and non-linear corrections"
371       
372        //set up values to send to auxiliary trig functions
373        xcenter = 64.5
374        ycenter = 64.5
375        x0 = realsread[16]
376        y0 = realsread[17]
377        sx = realsread[10]
378        sx3 = realsread[11]
379        sy = realsread[13]
380        sy3 = realsread[14]
381       
382        dtdist = 1000*realsread[18]     //sdd in mm
383        dtdis2 = dtdist^2
384       
385        xx0 = dc_fx(x0,sx,sx3,xcenter)
386        yy0 = dc_fy(y0,sy,sy3,ycenter)
387       
388        NVAR pixelsX = root:myGlobals:gNPixelsX
389//      NVAR pixelsY = root:myGlobals:gNPixelsY
390        //waves to contain repeated function calls
391        Make/O/N=(pixelsX) fyy,xx,yy            //Assumes square detector
392        ii=0
393        do
394                xi = ii
395                fyy[ii] = dc_fy(ii+1,sy,sy3,ycenter)
396                xx[ii] = dc_fxn(ii+1,sx,sx3,xcenter)
397                yy[ii] = dc_fym(ii+1,sy,sy3,ycenter)
398                ii+=1
399        while(ii<pixelsX)
400       
401//      Make/O/N=(pixelsX,pixelsX) SolidAngle
402       
403        ii=0
404        do
405                xi = ii
406                xd = dc_fx(ii+1,sx,sx3,xcenter)-xx0
407                jj=0
408                do
409                        yd = fyy[jj]-yy0
410                        //rad is the distance of pixel ij from the sample
411                        //domega is the ratio of the solid angle of pixel ij versus center pixel
412                        rad = sqrt(dtdis2 + xd^2 + yd^2)
413                        domega = rad/dtdist
414                        ratio = domega^3
415//                      solidAngle[ii][jj] = ratio                     
416                        xy = xx[ii]*yy[jj]
417                        data[ii][jj] *= xy*ratio
418                        jj+=1
419                while(jj<pixelsX)
420                ii+=1
421        while(ii<pixelsX)
422       
423        //clean up waves
424        Killwaves/Z fyy,xx,yy
425       
426        Return(0)
427End
428
429//trig function used by DetCorr()
430Function dc_fx(x,sx,sx3,xcenter)
431        Variable x,sx,sx3,xcenter
432       
433        Variable result
434       
435        result = sx3*tan((x-xcenter)*sx/sx3)
436        Return(result)
437End
438
439//trig function used by DetCorr()
440Function dc_fy(y,sy,sy3,ycenter)
441        Variable y,sy,sy3,ycenter
442       
443        Variable result
444       
445        result = sy3*tan((y-ycenter)*sy/sy3)
446        Return(result)
447End
448
449//trig function used by DetCorr()
450Function dc_fxn(x,sx,sx3,xcenter)
451        Variable x,sx,sx3,xcenter
452       
453        Variable result
454       
455        result = (cos((x-xcenter)*sx/sx3))^2
456        Return(result)
457End
458
459//trig function used by DetCorr()
460Function dc_fym(y,sy,sy3,ycenter)
461        Variable y,sy,sy3,ycenter
462       
463        Variable result
464       
465        result = (cos((y-ycenter)*sy/sy3))^2
466        Return(result)
467End
468
469//******************
470//direct port of the FORTRAN code for calculating the weighted
471//shifted element to add when beam centers in data headers do not match
472//(indices updated to [0,n-1] indexing rather than (1,n) of fortran
473//
474// as of IGOR 4.0, could be rewritten to pass-by-reference noadd, rather than wave, but the function
475// is so little used, it's not worth the time
476Function ShiftSum(DATA,ip,jp,XSHIFT,YSHIFT,noadd)
477        Wave data
478        Variable ip,jp,xshift,yshift
479        Wave noadd
480//
481//       COMPUTE WEIGHTED OFFSET ELEMENT SUM FOR USE IN SANS DATA
482//       ANALYSIS MODULES.
483//
484// "data" wave passed in is the current contents of the work file
485// sum_val is the return value of the function
486// "noadd" is passed back to the calling function as a one-point wave
487
488        Variable XDELTA,YDELTA,kk,II,JJ,ISHIFT,JSHIFT,sum_val
489        Make/O/N=4 iii,jjj,a
490
491//       -----------------------------------------------------------------
492
493        ISHIFT = trunc(XSHIFT)          // INTEGER PART, trunc gives int closest in dierction of zero
494        XDELTA = XSHIFT - ISHIFT        //FRACTIONAL PART.
495        JSHIFT = trunc(YSHIFT)
496        YDELTA = YSHIFT - JSHIFT
497        II = ip + ISHIFT
498        JJ = jp + JSHIFT
499
500//       SHIFT IS DEFINED AS A VECTOR ANCHORED AT THE STATIONARY CENTER
501//       AND POINTING TO THE MOVABLE CENTER.  THE MOVABLE FIELD IS THUS
502//       ACTUALLY MOVED BY -SHIFT.
503//
504        IF ((XDELTA>= 0) && (YDELTA >= 0))              // CASE I ---- "%&" is "and"
505                III[0] = II
506                JJJ[0] = JJ
507                III[1] = II + 1
508                JJJ[1] = JJ
509                III[2] = II + 1
510                JJJ[2] = JJ + 1
511                III[3] = II
512                JJJ[3] = JJ + 1
513                A[0] = (1. - XDELTA)*(1. - YDELTA)
514                A[1] = XDELTA*(1. - YDELTA)
515                A[2] = XDELTA*YDELTA
516                A[3] = (1. - XDELTA)*YDELTA
517        Endif
518        IF ((XDELTA >= 0) && (YDELTA < 0))              // CASE II.
519                III[0] = II
520                JJJ[0] = JJ
521                III[1] = II
522                JJJ[1] = JJ - 1
523                III[2] = II + 1
524                JJJ[2] = JJ - 1
525                III[3] = II + 1
526                JJJ[3] = JJ
527                A[0] = (1. - XDELTA)*(1. + YDELTA)
528                A[1] = (1. - XDELTA)*(-YDELTA)
529                A[2] = XDELTA*(-YDELTA)
530                A[3] = XDELTA*(1. + YDELTA)
531        Endif
532        IF ((XDELTA < 0) && (YDELTA >= 0))              // CASE III.
533                III[0] = II
534                JJJ[0] = JJ
535                III[1] = II
536                JJJ[1] = JJ + 1
537                III[2] = II - 1
538                JJJ[2] = JJ + 1
539                III[3] = II - 1
540                JJJ[3] = JJ
541                A[0] = (1. + XDELTA)*(1 - YDELTA)
542                A[1] = (1. + XDELTA)*YDELTA
543                A[2] = -XDELTA*YDELTA
544                A[3] = -XDELTA*(1. - YDELTA)
545        Endif
546        IF ((XDELTA < 0) && (YDELTA < 0))               //CASE IV.
547                III[0] = II
548                JJJ[0] = JJ
549                III[1] = II - 1
550                JJJ[1] = JJ
551                III[2] = II - 1
552                JJJ[2] = JJ - 1
553                III[3] = II
554                JJJ[3] = JJ - 1
555                A[0] = (1. + XDELTA)*(1. + YDELTA)
556                A[1] = -XDELTA*(1. + YDELTA)
557                A[2] = (-XDELTA)*(-YDELTA)
558                A[3] = (1. + XDELTA)*(-YDELTA)
559        Endif
560
561        NVAR pixelsX = root:myGlobals:gNPixelsX
562        NVAR pixelsY = root:myGlobals:gNPixelsY
563//check to see if iii[0],jjj[0] are valid detector elements, in [0,127]
564//if not set noadd[0] to 1, to let calling routine know NOT to add
565//        CALL TESTIJ(III(1),JJJ(1),OKIJ)
566        NOADD[0] = 0
567        if( (iii[0]<0) || (iii[0]>(pixelsX-1)) )
568                noadd[0] = 1
569        endif
570        if((jjj[0]<0) || (jjj[0]>(pixelsY-1)) )
571                noadd[0] = 1
572        endif
573       
574
575       
576        sum_val = 0.
577        kk = 0
578        Do
579                IF(JJJ[kk] == pixelsX)
580                        //do nothing
581                else
582                        sum_val += A[kk]*DATA[III[kk]][JJJ[kk]]
583                endif
584                kk+=1
585        while(kk<4)
586       
587        //clean up waves
588        KillWaves/z iii,jjj,a
589       
590        RETURN (sum_val)
591       
592End             //function ShiftSum
593
594//************************
595//unused testing procedure, may not be up-to-date with other procedures
596//check before re-implementing
597//
598Proc DIV_a_Workfile(type)
599        String type
600        Prompt type,"WORK data type",popup,"COR;SAM;EMP;BGD"
601       
602        //macro will take whatever is in SELECTED folder and DIVide it by the current
603        //contents of the DIV folder - the function will check for existence
604        //before proceeding
605       
606        Variable err
607        err = Divide_work(type)         //returns err = 1 if data doesn't exist in specified folders
608       
609        if(err)
610                Abort "error in Divide_work"
611        endif
612       
613        //contents are always dumped to CAL
614        type = "CAL"
615       
616        String newTitle = "WORK_"+type
617        DoWindow/F SANS_Data
618        DoWindow/T SANS_Data, newTitle
619        KillStrings/Z newTitle
620       
621        //need to update the display with "data" from the correct dataFolder
622        //reset the current displaytype to "type"
623        String/G root:myGlobals:gDataDisplayType=Type
624       
625        fRawWindowHook()
626       
627End
628
629//function will divide the contents of "type" folder with the contents of
630//the DIV folder
631// all data is converted to linear scale for the calculation
632//
633Function Divide_work(type)
634        String type
635       
636        //check for existence of data in type and DIV
637        // if the desired workfile doesn't exist, let the user know, and abort
638        String destPath=""
639        destPath = "root:"+Type + ":data"
640        if(WaveExists($destpath) == 0)
641                Print "There is no work file in "+type+"--Aborting"
642                Return(1)               //error condition
643        Endif
644        //check for DIV
645        // if the DIV workfile doesn't exist, let the user know,and abort
646        destPath = "root:DIV:data"
647        if(WaveExists($destpath) == 0)
648                Print "There is no work file in DIV --Aborting"
649                Return(1)               //error condition
650        Endif
651        //files exist, proceed
652       
653        //check for log-scaling of the "DIV" data and adjust if necessary
654        ConvertFolderToLinearScale("DIV")
655       
656        //copy type information to CAL, wiping out the old contents of the CAL folder first
657       
658        //destPath = "root:CAL"
659        //SetDataFolder destPath
660        //KillWaves/A/Z                 //get rid of the old data in CAL folder
661
662        //check for log-scaling of the "type" data and adjust if necessary
663        ConvertFolderToLinearScale(type)
664        //then continue
665
666        //copy from current dir (type)=destPath to CAL, overwriting CAL contents
667        destPath = "root:" + type
668        Duplicate/O $(destPath + ":data"),$"root:CAL:data"
669//      Duplicate/O $(destPath + ":vlegend"),$"root:CAL:vlegend"
670        Duplicate/O $(destPath + ":textread"),$"root:CAL:textread"
671        Duplicate/O $(destPath + ":integersread"),$"root:CAL:integersread"
672        Duplicate/O $(destPath + ":realsread"),$"root:CAL:realsread"
673        //need to save a copy of filelist string too (from the current type folder)
674        SVAR oldFileList = $(destPath + ":fileList")
675
676        //now switch to reference waves in CAL folder
677        destPath = "root:CAL"
678        //make appropriate wave references
679        Wave data=$(destPath + ":data")                                 // these wave references point to the data in CAL
680        Wave/t textread=$(destPath + ":textread")                       //that are to be directly operated on
681        Wave integersread=$(destPath + ":integersread")
682        Wave realsread=$(destPath + ":realsread")
683        Variable/G $(destPath + ":gIsLogScale")=0                       //make new flag in CAL folder, data is linear scale
684        //need to copy filelist string too
685        String/G $(destPath + ":fileList") = oldFileList
686
687        Wave div_data = $"root:DIV:data"                //hard-wired in....
688        //do the division, changing data in CAL
689        data /= div_data
690       
691        //update CAL header
692        textread[1] = date() + " " + time()             //date + time stamp
693       
694        Return(0)
695End
696
697//test procedure, not called anymore
698Proc AbsoluteScaling(type,c0,c1,c2,c3,c4,c5)
699        String type
700        Variable c0=1,c1=0.1,c2=0.95,c3=0.1,c4=1,c5=32.0
701        Prompt type,"WORK data type",popup,"CAL;COR;SAM"
702        Prompt c0, "Sample Transmission"
703        Prompt c1, "Sample Thickness (cm)"
704        Prompt c2, "Standard Transmission"
705        Prompt c3, "Standard Thickness (cm)"
706        Prompt c4, "I(0) from standard fit (normalized to 1E8 monitor cts)"
707        Prompt c5, "Standard Cross-Section (cm-1)"
708
709        Variable err
710        //call the function to do the math
711        //data from "type" will be scaled and deposited in ABS
712        err = Absolute_Scale(type,c0,c1,c2,c3,c4,c5)
713       
714        if(err)
715                Abort "Error in Absolute_Scale()"
716        endif
717       
718        //contents are always dumped to ABS
719        type = "ABS"
720       
721        String newTitle = "WORK_"+type
722        DoWindow/F SANS_Data
723        DoWindow/T SANS_Data, newTitle
724        KillStrings/Z newTitle
725       
726        //need to update the display with "data" from the correct dataFolder
727        //reset the current displaytype to "type"
728        String/G root:myGlobals:gDataDisplayType=Type
729       
730        fRawWindowHook()
731       
732End
733
734//s_ is the standard
735//w_ is the "work" file
736//both are work files and should already be normalized to 10^8 monitor counts
737Function Absolute_Scale(type,w_trans,w_thick,s_trans,s_thick,s_izero,s_cross)
738        String type
739        Variable w_trans,w_thick,s_trans,s_thick,s_izero,s_cross
740       
741        //convert the "type" data to absolute scale using the given standard information
742        //copying the "type" waves to ABS
743       
744        //check for existence of data, rescale to linear if needed
745        String destPath
746        //check for "type"
747        destPath = "root:"+Type + ":data"
748        if(WaveExists($destpath) == 0)
749                Print "There is no work file in "+type+"--Aborting"
750                Return(1)               //error condition
751        Endif
752        //check for log-scaling of the "type" data and adjust if necessary
753        destPath = "root:"+Type
754        NVAR gIsLogScale = $(destPath + ":gIsLogScale")
755        if(gIsLogScale)
756                Duplicate/O $(destPath + ":linear_data") $(destPath + ":data")//back to linear scale
757                Variable/G $(destPath + ":gIsLogScale")=0       //the "type" data is not logscale anymore
758        endif
759       
760        //copy "oldtype" information to ABS
761        //overwriting out the old contents of the ABS folder (/O option in Duplicate)
762        //copy over the waves data,vlegend,text,integers,reals(read)
763
764        String oldType= "root:"+type            //this is where the data to be absoluted is
765        //copy from current dir (type) to ABS, defined by destPath
766        Duplicate/O $(oldType + ":data"),$"root:ABS:data"
767//      Duplicate/O $(oldType + ":vlegend"),$"root:ABS:vlegend"
768        Duplicate/O $(oldType + ":textread"),$"root:ABS:textread"
769        Duplicate/O $(oldType + ":integersread"),$"root:ABS:integersread"
770        Duplicate/O $(oldType + ":realsread"),$"root:ABS:realsread"
771        //need to save a copy of filelist string too (from the current type folder)
772        SVAR oldFileList = $(oldType + ":fileList")
773        //need to copy filelist string too
774        String/G $"root:ABS:fileList" = oldFileList
775       
776        //now switch to ABS folder
777        //make appropriate wave references
778        WAVE data=$"root:ABS:data"                                      // these wave references point to the "type" data in ABS
779        WAVE/T textread=$"root:ABS:textread"                    //that are to be directly operated on
780        WAVE integersread=$"root:ABS:integersread"
781        WAVE realsread=$"root:ABS:realsread"
782        Variable/G $"root:ABS:gIsLogscale"=0                    //make new flag in ABS folder, data is linear scale
783       
784        //do the actual absolute scaling here, modifying the data in ABS
785        Variable defmon = 1e8,w_moncount,s1,s2,s3,s4
786       
787        w_moncount = realsread[0]               //monitor count in "type"
788        if(w_moncount == 0)
789                //zero monitor counts will give divide by zero ---
790                DoAlert 0,"Total monitor count in data file is zero. No rescaling of data"
791                Return(1)               //report error
792        Endif
793       
794        //calculate scale factor
795        s1 = defmon/realsread[0]                //[0] is monitor count (s1 should be 1)
796        s2 = s_thick/w_thick
797        s3 = s_trans/w_trans
798        s4 = s_cross/s_izero
799       
800        data *= s1*s2*s3*s4
801       
802        //********* 15APR02
803        // DO NOt correct for atenuators here - the COR step already does this, putting all of the data one equal
804        // footing (zero atten) before doing the subtraction.
805        //
806        //correct for attenuation of the sample (at NG5, NG7 attenuator table is used)
807//      Variable attenNo,attenFactor,lambda
808//      String fileStr=textRead[3]
809//      attenNo = realsRead[3]
810//      lambda = realsRead[26]
811//      attenFactor = AttenuationFactor(fileStr,lambda,attenNo)
812//      data /= attenFactor             //atten factor is less than one
813        //Print "ABS data multiplied by  ",s1*s2*s3*s4/attenFactor
814       
815        //update the ABS header information
816        textread[1] = date() + " " + time()             //date + time stamp
817       
818        Return (0) //no error
819End
820
821//*************
822// start of section of functions used for workfile math panel
823//*************
824
825
826//function will copy the contents of oldtype folder to newtype folder
827//converted to linear scale before copying
828//******data in newtype is overwritten********
829//
830Function CopyWorkContents(oldtype,newtype)
831        String oldtype,newtype
832       
833        //check for existence of data in oldtype
834        // if the desired workfile doesn't exist, let the user know, and abort
835        String destPath=""
836        destPath = "root:"+oldType + ":data"
837        if(WaveExists($destpath) == 0)
838                Print "There is no work file in "+oldtype+"--Aborting"
839                Return(1)               //error condition
840        Endif
841       
842        //check for log-scaling of the "type" data and adjust if necessary
843        ConvertFolderToLinearScale(oldtype)
844        Fix_LogLinButtonState(0)                //make sure the button reflects the new linear scaling
845        //then continue
846
847        //copy from current dir (type)=destPath to newtype, overwriting newtype contents
848        destPath = "root:" + oldtype
849        Duplicate/O $(destPath + ":data"),$("root:"+newtype+":data")
850        Duplicate/O $(destPath + ":textread"),$("root:"+newtype+":textread")
851        Duplicate/O $(destPath + ":integersread"),$("root:"+newtype+":integersread")
852        Duplicate/O $(destPath + ":realsread"),$("root:"+newtype+":realsread")
853        //need to save a copy of filelist string too (from the current type folder)
854        SVAR oldFileList = $(destPath + ":fileList")
855
856        //now switch to reference waves in newtype folder
857        destPath = "root:"+newtype
858        Variable/G $(destPath + ":gIsLogScale")=0                       //make new flag in newtype folder, data is linear scale
859        //need to copy filelist string too
860        String/G $(destPath + ":fileList") = oldFileList
861
862        Return(0)
863End
864
865//Entry procedure from main panel
866//
867Proc CopyWorkFolder(oldType,newType)
868        String oldType,newType
869        Prompt oldType,"Source WORK data type",popup,"SAM;EMP;BGD;DIV;COR;CAL;RAW;ABS;STO;SUB;DRK;"
870        Prompt newType,"Destination WORK data type",popup,"SAM;EMP;BGD;DIV;COR;CAL;RAW;ABS;STO;SUB;DRK;"
871//      Prompt oldType,"Source WORK data type",popup,"AAA;BBB;CCC;DDD;EEE;FFF;GGG;"
872//      Prompt newType,"Destination WORK data type",popup,"AAA;BBB;CCC;DDD;EEE;FFF;GGG;"
873
874        // data folder "old" will be copied to "new" (and will overwrite)
875        CopyWorkContents(oldtype,newtype)
876End
877
878//initializes datafolder and constants necessary for the workfilemath panel
879//
880Proc Init_WorkMath()
881        //create the data folder
882        //String str = "AAA;BBB;CCC;DDD;EEE;FFF;GGG;"
883        String str = "File_1;File_2;Result;"
884        NewDataFolder/O/S root:myGlobals:WorkMath
885        String/G gFolderList=str
886        Variable ii=0,num=itemsinlist(str)
887        do
888                Execute "NewDataFolder/O "+StringFromList(ii, str ,";")
889                ii+=1
890        while(ii<num)
891        Variable/G const1=1,const2=1
892       
893        SetDataFolder root:
894End
895
896//entry procedure to invoke the workfilemath panel, initializes if needed
897//
898Proc Show_WorkMath_Panel()
899        DoWindow/F WorkFileMath
900        if(V_flag==0)
901                Init_WorkMath()
902                WorkFileMath()
903        Endif
904End
905
906//attempts to perform the selected math operation based on the selections in the panel
907// aborts with an error condition if operation can't be completed
908// or puts the final answer in the Result folder, and displays the selected data
909//
910Function WorkMath_DoIt_ButtonProc(ctrlName) : ButtonControl
911        String ctrlName
912
913        String str1,str2,oper,dest = "Result"
914        String pathStr,workMathStr="myGlobals:WorkMath:"
915       
916        //get the panel selections (these are the names of the files on disk)
917        PathInfo catPathName
918        pathStr=S_Path
919        ControlInfo popup0
920        str1=S_Value
921        ControlInfo popup1
922        str2=S_Value
923        ControlInfo popup2
924        oper=S_Value
925       
926        //check that something has been selected for operation and destination
927        if(cmpstr(oper,"Operation")==0)
928                Abort "Select a math operand from the popup"
929        Endif
930
931        //constants from globals
932        NVAR const1=root:myGlobals:WorkMath:const1
933        NVAR const2=root:myGlobals:WorkMath:const2
934        Printf "(%g)%s %s (%g)%s = %s\r", const1,str1,oper,const2,str2,dest
935        //check for proper folders (all 3 must be different)
936       
937        //load the data in here...
938        //set #1
939        Load_NamedASC_File(pathStr+str1,workMathStr+"File_1")
940       
941        NVAR pixelsX = root:myGlobals:gNPixelsX
942        NVAR pixelsY = root:myGlobals:gNPixelsY
943       
944        WAVE/Z data1=$("root:"+workMathStr+"File_1:data")
945        If(cmpstr(str2,"UNIT MATRIX")==0)
946                Make/O/N=(pixelsX,pixelsY) root:myGlobals:WorkMath:data         //don't put in File_2 folder
947                Wave/Z data2 =  root:myGlobals:WorkMath:data                    //it's not real data!
948                data2=1
949        else
950                //Load set #2
951                Load_NamedASC_File(pathStr+str2,workMathStr+"File_2")
952                WAVE/Z data2=$("root:"+workMathStr+"File_2:data")
953        Endif
954
955        ///////
956       
957        //now that we know that data exists, convert each of the operands to linear scale
958        ConvertFolderToLinearScale(workMathStr+"File_1")
959        If(cmpstr(str2,"UNIT MATRIX")!=0)
960                ConvertFolderToLinearScale(workMathStr+"File_2")                //don't need to convert unit matrix to linear
961        endif
962        //copy contents of str1 folder to dest and create the wave ref (it will exist)
963        CopyWorkContents(workMathStr+"File_1",workMathStr+dest)
964        WAVE/Z destData=$("root:"+workMathStr+dest+":data")
965       
966        //dispatch
967        strswitch(oper)
968                case "*":               //multiplication
969                        destData = const1*data1 * const2*data2
970                        break   
971                case "_":               //subtraction
972                        destData = const1*data1 - const2*data2
973                        break
974                case "/":               //division
975                        destData = (const1*data1) / (const2*data2)
976                        break
977                case "+":               //addition
978                        destData = const1*data1 + const2*data2
979                        break                   
980        endswitch
981       
982        //show the result
983        WorkMath_Display_PopMenuProc("",0,"Result")
984End
985
986// closes the panel and kills the data folder when done
987//
988Function WorkMath_Done_ButtonProc(ctrlName) : ButtonControl
989        String ctrlName
990       
991        DoAlert 1,"Closing the panel will kill all of the data you have loaded into memory. Do you want to continue?"
992        If(V_Flag==2)
993                return(0)               //don't do anything
994        Endif
995        //kill the panel
996        DoWindow/K WorkFileMath
997        //wipe out the data folder of globals
998        SVAR dataType=root:myGlobals:gDataDisplayType
999        if(strsearch(dataType, "myGlobals", 0 ) != -1)          //kill the SANS_Data graph if needed
1000                DoWindow/K SANS_Data
1001        Endif
1002        KillDataFolder root:myGlobals:WorkMath
1003End
1004
1005// loads data into the specified folder
1006//
1007// currently unused since button has been removed from panel
1008//
1009Function WorkMath_Load_ButtonProc(ctrlName) : ButtonControl
1010        String ctrlName
1011       
1012        String destStr=""
1013        SVAR folderList=root:myGlobals:WorkMath:gFolderList
1014        Prompt destStr,"Select the destination folder",popup,folderList
1015        DoPrompt "Folder for ASC Load",destStr
1016       
1017        if(V_flag==1)
1018                return(1)               //user abort, do nothing
1019        Endif
1020       
1021        String destFolder = "myGlobals:WorkMath:"+destStr
1022       
1023        Load_ASC_File("Pick the ASC file",destFolder)
1024End
1025
1026// changes the display of the SANS_Data window based on popped data type
1027// first loads in the data from the File1 or File2 popup as needed
1028// then displays the selcted dataset, if it exists
1029// makes use of procedure from DisplayUtils
1030//
1031// - Always replaces File1 or File2 with fresh data from disk
1032//
1033Function WorkMath_Display_PopMenuProc(ctrlName,popNum,popStr) : PopupMenuControl
1034        String ctrlName
1035        Variable popNum
1036        String popStr
1037       
1038        String folder="myGlobals:WorkMath:",pathStr,str1
1039
1040        PathInfo catPathName
1041        pathStr=S_Path
1042       
1043        //if display result, just do it and return
1044        if(cmpstr(popStr,"Result")==0)
1045                Execute "ChangeDisplay(\""+folder+popstr+"\")"
1046                return(0)
1047        endif
1048        // if file1 or file2, load in the data and display
1049        if(cmpstr(popStr,"File_1")==0)
1050                ControlInfo popup0
1051                str1 = S_Value
1052        Endif
1053        if(cmpstr(popStr,"File_2")==0)
1054                ControlInfo popup1
1055                str1 = S_Value
1056        Endif
1057        //don't load or display the unit matrix
1058        Print str1
1059        if(cmpstr(str1,"UNIT MATRIX")!=0)
1060                Load_NamedASC_File(pathStr+str1,folder+popStr)
1061                //change the display
1062                Execute "ChangeDisplay(\""+folder+popstr+"\")"
1063        endif
1064        return(0)       
1065End
1066
1067//simple panel to do workfile arithmetic
1068//
1069Proc WorkFileMath()
1070        PauseUpdate; Silent 1           // building window...
1071        NewPanel /W=(610,211,880,490)/K=2 as "Work File Math"           // replace /K=2 flag
1072        DoWindow/C WorkFileMath
1073        ModifyPanel cbRGB=(47802,54484,6682)
1074        ModifyPanel fixedSize=1
1075        SetDrawLayer UserBack
1076        DrawLine 6,166,214,166
1077        SetDrawEnv fstyle= 4
1078        DrawText 10,34,"File #1:"
1079        SetDrawEnv fstyle= 4
1080        DrawText 13,129,"File #2:"
1081        DrawText 78,186,"= Result"
1082        Button button0,pos={28,245},size={50,20},proc=WorkMath_DoIt_ButtonProc,title="Do It"
1083        Button button0,help={"Performs the specified arithmetic"}
1084        Button button1,pos={183,245},size={50,20},proc=WorkMath_Done_ButtonProc,title="Done"
1085        Button button1,help={"Closes the panel"}
1086//      Button button2,pos={30,8},size={110,20},proc=WorkMath_Load_ButtonProc,title="Load ASC Data"
1087//      Button button2,help={"Loads ASC data files into the specified folder"}
1088        Button button3,pos={205,8},size={25,20},proc=ShowWorkMathHelp,title="?"
1089        Button button3,help={"Show help file for math operations on 2-D data sets"}
1090        SetVariable setvar0,pos={9,46},size={70,15},title=" "
1091        SetVariable setvar0,limits={-Inf,Inf,0},value= root:myGlobals:WorkMath:const1
1092        SetVariable setvar0,help={"Multiplicative constant for the first dataset"}
1093        PopupMenu popup0,pos={89,44},size={84,20},title="X  "
1094        PopupMenu popup0,mode=1,popvalue="1st Set",value= ASC_FileList()
1095        PopupMenu popup0,help={"Selects the first dataset for the operation"}
1096        PopupMenu popup1,pos={93,136},size={89,20},title="X  "
1097        PopupMenu popup1,mode=1,popvalue="2nd Set",value= "UNIT MATRIX;"+ASC_FileList()
1098        PopupMenu popup1,help={"Selects the second dataset for the operation"}
1099        PopupMenu popup2,pos={50,82},size={70,20},title="Operator  "
1100        PopupMenu popup2,mode=3,popvalue="Operation",value= #"\"+;_;*;/;\""
1101        PopupMenu popup2,help={"Selects the mathematical operator"}
1102        SetVariable setvar1,pos={13,139},size={70,15},title=" "
1103        SetVariable setvar1,limits={-Inf,Inf,0},value= root:myGlobals:WorkMath:const2
1104        SetVariable setvar1,help={"Multiplicative constant for the second dataset"}
1105//      PopupMenu popup3,pos={27,167},size={124,20},title=" = Destination"
1106//      PopupMenu popup3,mode=1,popvalue="Destination",value= root:myGlobals:WorkMath:gFolderList
1107//      PopupMenu popup3,help={"Selects the destination folder"}
1108        PopupMenu popup4,pos={55,204},size={103,20},proc=WorkMath_Display_PopMenuProc,title="Display"
1109        PopupMenu popup4,mode=3,value= "File_1;File_2;Result;"
1110        PopupMenu popup4,help={"Displays the data in the specified folder"}
1111EndMacro
1112
1113//jump to the help topic
1114Function ShowWorkMathHelp(ctrlName) : ButtonControl
1115        String ctrlName
1116        DisplayHelpTopic/K=1 "SANS Data Reduction Tutorial[2-D Work File Arithmetic]"
1117End
1118
1119//utility function to clear the contents of a data folder
1120//won't clear data that is in use -
1121//
1122Function ClearDataFolder(type)
1123        String type
1124       
1125        SetDataFolder $("root:"+type)
1126        KillWaves/a/z
1127        KillStrings/a/z
1128        KillVariables/a/z
1129        SetDataFolder root:
1130End
1131
1132
1133
1134//fileStr must be the FULL path and filename on disk
1135//destFolder is the path to the Igor folder where the data is to be deposited
1136// - "myGlobals:WorkMath:File_1" for example, compatible with SANS_Data display type
1137//
1138Function Load_NamedASC_File(fileStr,destFolder)
1139        String fileStr,destFolder
1140
1141        Variable refnum
1142       
1143        //read in the data
1144        ReadASCData(fileStr,destFolder)
1145
1146        //the calling macro must change the display type
1147        String/G root:myGlobals:gDataDisplayType=destFolder
1148       
1149        FillFakeHeader_ASC(destFolder)          //uses info on the panel, if available
1150
1151        //data is displayed here, and needs header info
1152       
1153        fRawWindowHook()
1154       
1155        return(0)
1156End
1157
1158
1159//function called by the main entry procedure (the load button)
1160//loads data into the specified folder, and wipes out what was there
1161//
1162//aborts if no file was selected
1163//
1164// reads the data in if all is OK
1165//
1166// currently unused, as load button has been replaced
1167//
1168Function Load_ASC_File(msgStr,destFolder)
1169        String msgStr,destFolder
1170
1171        String filename="",pathStr=""
1172        Variable refnum
1173
1174        //check for the path
1175        PathInfo catPathName
1176        If(V_Flag==1)           //      /D does not open the file
1177                Open/D/R/T="????"/M=(msgStr)/P=catPathName refNum
1178        else
1179                Open/D/R/T="????"/M=(msgStr) refNum
1180        endif
1181        filename = S_FileName           //get the filename, or null if canceled from dialog
1182        if(strlen(filename)==0)
1183                //user cancelled, abort
1184                SetDataFolder root:
1185                Abort "No file selected, action aborted"
1186        Endif
1187       
1188        //read in the data
1189        ReadASCData(filename,destFolder)
1190
1191        //the calling macro must change the display type
1192        String/G root:myGlobals:gDataDisplayType=destFolder
1193       
1194        FillFakeHeader_ASC(destFolder)          //uses info on the panel, if available
1195
1196        //data is displayed here, and needs header info
1197       
1198        fRawWindowHook()
1199       
1200        return(0)
1201End
1202
1203
1204
1205//function called by the popups to get a file list of data that can be sorted
1206// this procedure simply removes the raw data files from the string - there
1207//can be lots of other junk present, but this is very fast...
1208//
1209Function/S ASC_FileList()
1210
1211        String list="",newList="",item=""
1212        Variable num,ii
1213       
1214        //check for the path
1215        PathInfo catPathName
1216        if(V_Flag==0)
1217                DoAlert 0, "Data path does not exist - pick the data path from the button on the main panel"
1218                Return("")
1219        Endif
1220       
1221        list = IndexedFile(catpathName,-1,"????")
1222        num=ItemsInList(list,";")
1223        //print "num = ",num
1224        for(ii=(num-1);ii>=0;ii-=1)
1225                item = StringFromList(ii, list  ,";")
1226                //simply remove all that are not raw data files (SA1 SA2 SA3)
1227                if( !stringmatch(item,"*.SA1*") && !stringmatch(item,"*.SA2*") && !stringmatch(item,"*.SA3*") )
1228                        if( !stringmatch(item,".*") && !stringmatch(item,"*.pxp") && !stringmatch(item,"*.DIV"))                //eliminate mac "hidden" files, pxp, and div files
1229                                if(!stringmatch(item,"*.AVE") && !stringmatch(item,"*.ABS"))
1230                                        newlist += item + ";"
1231                                endif
1232                        endif
1233                endif
1234        endfor
1235        //remove VAX version numbers
1236        newList = RemoveVersNumsFromList(newList)
1237        //sort
1238        newList = SortList(newList,";",0)
1239
1240        return newlist
1241End
Note: See TracBrowser for help on using the repository browser.