source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/SANS/WorkFileUtilsLP.ipf @ 575

Last change on this file since 575 was 570, checked in by srkline, 13 years ago

Change (1):
In preparation for release, updated pragma IgorVersion?=6.1 in all procedures

Change (2):
As a side benefit of requiring 6.1, we can use the MultiThread? keyword to thread any model function we like. The speed benefit is only noticeable on functions that require at least one integration and at least 100 points (resolution smearing is NOT threaded, too many threadSafe issues, too little benefit). I have chosen to use the MultiThread? only on the XOP assignment. In the Igor code there are too many functions that are not explicitly declared threadsafe, making for a mess.

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