source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/SANS/NCNR_Utils.ipf @ 515

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

A bunch of random changes:
-SASCALC - added the 2.5 cm aperture NG3/7g/polarizer back in, but made the 5 cm the default
-Some fiddling with 2D functionality to enable 2D resolution smearing. Still a work in progress
-Added two new model functions, and added them to the list.
-Changes to the wrapper for the new release to generate kw=val strings as needed for each function
and its coefficients and parameters. This behavior has been changed in the new release, so this
fix should keep old analysis experiments compatible with the new version.

File size: 43.2 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma version=5.0
3#pragma IgorVersion=6.0
4
5// this file contains globals and functions that are specific to a
6// particular facility or data file format
7// branched out 29MAR07 - SRK
8//
9// functions are either labeled with the procedure file that calls them,
10// or noted that they are local to this file
11
12
13// initializes globals that are specific to a particular facility
14// - number of XY pixels
15// - pixexl resolution [cm]
16// - detector deadtime constant [s]
17//
18// called by Initialize.ipf
19//
20Function InitFacilityGlobals()
21
22        //Detector -specific globals
23        Variable/G root:myGlobals:gNPixelsX=128
24        Variable/G root:myGlobals:gNPixelsY=128
25       
26        // as of Jan2008, detector pixel sizes are read directly from the file header, so they MUST
27        // be set correctly in instr.cfg
28        Variable/G root:myGlobals:PixelResNG3_ILL = 1.0         //pixel resolution in cm
29        Variable/G root:myGlobals:PixelResNG5_ILL = 1.0
30        Variable/G root:myGlobals:PixelResNG7_ILL = 1.0
31        Variable/G root:myGlobals:PixelResNG3_ORNL = 0.5
32        Variable/G root:myGlobals:PixelResNG5_ORNL = 0.5
33        Variable/G root:myGlobals:PixelResNG7_ORNL = 0.5
34        Variable/G root:myGlobals:PixelResDefault = 0.5
35       
36        Variable/G root:myGlobals:DeadtimeNG3_ILL = 3.0e-6              //deadtime in seconds
37        Variable/G root:myGlobals:DeadtimeNG5_ILL = 3.0e-6
38        Variable/G root:myGlobals:DeadtimeNG7_ILL = 3.0e-6
39        Variable/G root:myGlobals:DeadtimeNG3_ORNL = 3.4e-6
40        Variable/G root:myGlobals:DeadtimeNG5_ORNL = 0.6e-6             //as of 9 MAY 2002
41        Variable/G root:myGlobals:DeadtimeNG7_ORNL = 3.4e-6
42        Variable/G root:myGlobals:DeadtimeDefault = 3.4e-6
43       
44        //new 11APR07
45        Variable/G root:myGlobals:BeamstopXTol = -8                     // (cm) is BS Xpos is -5 cm or less, it's a trans measurement
46        // sample aperture offset is NOT stored in the VAX header, but it should be
47        // - when it is, remove the global and write an accessor AND make a place for
48        // it in the RealsRead
49        Variable/G root:myGlobals:apOff = 5.0                           // (cm) distance from sample aperture to sample position
50
51End
52
53
54//**********************
55// Resolution calculation - used by the averaging routines
56// to calculate the resolution function at each q-value
57// - the return value is not used
58//
59// equivalent to John's routine on the VAX Q_SIGMA_AVE.FOR
60// Incorporates eqn. 3-15 from J. Appl. Cryst. (1995) v. 28 p105-114
61//
62// - 21 MAR 07 uses projected BS diameter on the detector
63// - APR 07 still need to add resolution with lenses. currently there is no flag in the
64//          raw data header to indicate the presence of lenses.
65//
66// - Aug 07 - added input to switch calculation based on lenses (==1 if in)
67//
68// - called by CircSectAvg.ipf and RectAnnulAvg.ipf
69//
70// passed values are read from RealsRead
71// except DDet and apOff, which are set from globals before passing
72//
73//
74Function/S getResolution(inQ,lambda,lambdaWidth,DDet,apOff,S1,S2,L1,L2,BS,del_r,usingLenses,SigmaQ,QBar,fSubS)
75        Variable inQ, lambda, lambdaWidth, DDet, apOff, S1, S2, L1, L2, BS, del_r,usingLenses
76        Variable &fSubS, &QBar, &SigmaQ         //these are the output quantities at the input Q value
77       
78        //lots of calculation variables
79        Variable a2, q_small, lp, v_lambda, v_b, v_d, vz, yg, v_g
80        Variable r0, delta, inc_gamma, fr, fv, rmd, v_r1, rm, v_r
81
82        //Constants
83        Variable vz_1 = 3.956e5         //velocity [cm/s] of 1 A neutron
84        Variable g = 981.0                              //gravity acceleration [cm/s^2]
85
86        String results
87        results ="Failure"
88
89        S1 *= 0.5*0.1                   //convert to radius and [cm]
90        S2 *= 0.5*0.1
91
92        L1 *= 100.0                     // [cm]
93        L1 -= apOff                             //correct the distance
94
95        L2 *= 100.0
96        L2 += apOff
97        del_r *= 0.1                            //width of annulus, convert mm to [cm]
98       
99        BS *= 0.5*0.1                   //nominal BS diameter passed in, convert to radius and [cm]
100        // 21 MAR 07 SRK - use the projected BS diameter, based on a point sample aperture
101        Variable LB
102        LB = 20.1 + 1.61*BS                     //distance in cm from beamstop to anode plane (empirical)
103        BS = bs + bs*lb/(l2-lb)         //adjusted diameter of shadow from parallax
104       
105        //Start resolution calculation
106        a2 = S1*L2/L1 + S2*(L1+L2)/L1
107        q_small = 2.0*Pi*(BS-a2)*(1.0-lambdaWidth)/(lambda*L2)
108        lp = 1.0/( 1.0/L1 + 1.0/L2)
109
110        v_lambda = lambdaWidth^2/6.0
111       
112//      if(usingLenses==1)                      //SRK 2007
113        if(usingLenses != 0)                    //SRK 2008 allows for the possibility of different numbers of lenses in header
114                v_b = 0.25*(S1*L2/L1)^2 +0.25*(2/3)*(lambdaWidth/lambda)^2*(S2*L2/lp)^2         //correction to 2nd term
115        else
116                v_b = 0.25*(S1*L2/L1)^2 +0.25*(S2*L2/lp)^2              //original form
117        endif
118       
119        v_d = (DDet/2.3548)^2 + del_r^2/12.0
120        vz = vz_1 / lambda
121        yg = 0.5*g*L2*(L1+L2)/vz^2
122        v_g = 2.0*(2.0*yg^2*v_lambda)                                   //factor of 2 correction, B. Hammouda, 2007
123
124        r0 = L2*tan(2.0*asin(lambda*inQ/(4.0*Pi) ))
125        delta = 0.5*(BS - r0)^2/v_d
126
127        if (r0 < BS)
128                inc_gamma=exp(gammln(1.5))*(1-gammp(1.5,delta))
129        else
130                inc_gamma=exp(gammln(1.5))*(1+gammp(1.5,delta))
131        endif
132
133        fSubS = 0.5*(1.0+erf( (r0-BS)/sqrt(2.0*v_d) ) )
134        if (fSubS <= 0.0)
135                fSubS = 1.e-10
136        endif
137        fr = 1.0 + sqrt(v_d)*exp(-1.0*delta) /(r0*fSubS*sqrt(2.0*Pi))
138        fv = inc_gamma/(fSubS*sqrt(Pi)) - r0^2*(fr-1.0)^2/v_d
139
140        rmd = fr*r0
141        v_r1 = v_b + fv*v_d +v_g
142
143        rm = rmd + 0.5*v_r1/rmd
144        v_r = v_r1 - 0.5*(v_r1/rmd)^2
145        if (v_r < 0.0)
146                v_r = 0.0
147        endif
148        QBar = (4.0*Pi/lambda)*sin(0.5*atan(rm/L2))
149        SigmaQ = QBar*sqrt(v_r/rmd^2 +v_lambda)
150
151        results = "success"
152        Return results
153End
154
155//
156//
157//      this should end up in NCNR_Utils once it's fully functional
158//
159// lots of unnecessary junk...
160//
161//**********************
162// 2D resolution function calculation - in terms of X and Y
163//
164// based on notes from David Mildner, 2008
165//
166// - 21 MAR 07 uses projected BS diameter on the detector
167// - APR 07 still need to add resolution with lenses. currently there is no flag in the
168//          raw data header to indicate the presence of lenses.
169//
170// - Aug 07 - added input to switch calculation based on lenses (==1 if in)
171//
172// passed values are read from RealsRead
173// except DDet and apOff, which are set from globals before passing
174//
175// phi is the azimuthal angle, CCW from +x axis
176// r_dist is the real-space distance from ctr of detector to QxQy pixel location
177//
178Function/S get2DResolution(inQ,phi,lambda,lambdaWidth,DDet,apOff,S1,S2,L1,L2,BS,del_r,usingLenses,r_dist,SigmaQX,SigmaQY,fSubS)
179        Variable inQ, phi,lambda, lambdaWidth, DDet, apOff, S1, S2, L1, L2, BS, del_r,usingLenses,r_dist
180        Variable &SigmaQX,&SigmaQY,&fSubS               //these are the output quantities at the input Q value
181       
182        //lots of calculation variables
183        Variable a2, lp, v_lambda, v_b, v_d, vz, yg, v_g
184        Variable r0, delta, inc_gamma, fr, fv, rmd, v_r1, rm, v_r
185
186        //Constants
187        Variable vz_1 = 3.956e5         //velocity [cm/s] of 1 A neutron
188        Variable g = 981.0                              //gravity acceleration [cm/s^2]
189        Variable h_m = 3995                             // h/m [=] A*m/s
190
191        String results
192        results ="Failure"
193
194        S1 *= 0.5*0.1                   //convert to radius and [cm]
195        S2 *= 0.5*0.1
196
197        L1 *= 100.0                     // [cm]
198        L1 -= apOff                             //correct the distance
199
200        L2 *= 100.0
201        L2 += apOff
202        del_r *= 0.1                            //width of annulus, convert mm to [cm]
203       
204        BS *= 0.5*0.1                   //nominal BS diameter passed in, convert to radius and [cm]
205        // 21 MAR 07 SRK - use the projected BS diameter, based on a point sample aperture
206        Variable LB
207        LB = 20.1 + 1.61*BS                     //distance in cm from beamstop to anode plane (empirical)
208        BS = bs + bs*lb/(l2-lb)         //adjusted diameter of shadow from parallax
209       
210        //Start resolution calculation
211        a2 = S1*L2/L1 + S2*(L1+L2)/L1
212        lp = 1.0/( 1.0/L1 + 1.0/L2)
213
214        v_lambda = lambdaWidth^2/6.0
215       
216//      if(usingLenses==1)                      //SRK 2007
217        if(usingLenses != 0)                    //SRK 2008 allows for the possibility of different numbers of lenses in header
218                v_b = 0.25*(S1*L2/L1)^2 +0.25*(2/3)*(lambdaWidth/lambda)^2*(S2*L2/lp)^2         //correction to 2nd term
219        else
220                v_b = 0.25*(S1*L2/L1)^2 +0.25*(S2*L2/lp)^2              //original form
221        endif
222       
223        v_d = (DDet/2.3548)^2 + del_r^2/12.0
224        vz = vz_1 / lambda
225        yg = 0.5*g*L2*(L1+L2)/vz^2
226        v_g = 2.0*(2.0*yg^2*v_lambda)                                   //factor of 2 correction, B. Hammouda, 2007
227
228        r0 = L2*tan(2.0*asin(lambda*inQ/(4.0*Pi) ))
229        delta = 0.5*(BS - r0)^2/v_d
230
231        if (r0 < BS)
232                inc_gamma=exp(gammln(1.5))*(1-gammp(1.5,delta))
233        else
234                inc_gamma=exp(gammln(1.5))*(1+gammp(1.5,delta))
235        endif
236
237        fSubS = 0.5*(1.0+erf( (r0-BS)/sqrt(2.0*v_d) ) )
238        if (fSubS <= 0.0)
239                fSubS = 1.e-10
240        endif
241//      fr = 1.0 + sqrt(v_d)*exp(-1.0*delta) /(r0*fSubS*sqrt(2.0*Pi))
242//      fv = inc_gamma/(fSubS*sqrt(Pi)) - r0^2*(fr-1.0)^2/v_d
243//
244//      rmd = fr*r0
245//      v_r1 = v_b + fv*v_d +v_g
246//
247//      rm = rmd + 0.5*v_r1/rmd
248//      v_r = v_r1 - 0.5*(v_r1/rmd)^2
249//      if (v_r < 0.0)
250//              v_r = 0.0
251//      endif
252
253        Variable kap,a_val
254       
255        kap = 2*pi/lambda
256        a_val = (L1+L2)*g/2/(h_m)^2
257
258//      lambdaWidth = 0.5       
259        SigmaQX = 3*(S1/L1)^2 + 3*(S2/LP)^2 + 2*(DDet/L2)^2 + 2*(r_dist/L2)^2*(lambdaWidth)^2*(cos(phi))^2
260
261        SigmaQY = 3*(S1/L1)^2 + 3*(S2/LP)^2 + 2*(DDet/L2)^2 + 2*(r_dist/L2)^2*(lambdaWidth)^2*(sin(phi))^2 + 8*(a_val/L2)^2*lambda^4*lambdaWidth^2
262//      SigmaQY = 3*(S1/L1)^2 + 3*(S2/LP)^2 + 2*(DDet/L2)^2 + 2*(r_dist/L2)^2*(lambdaWidth)^2*(sin(phi))^2
263
264        SigmaQX = sqrt(kap*kap/12*SigmaQX)
265        SigmaQy = sqrt(kap*kap/12*SigmaQY)
266
267        results = "success"
268        Return results
269End
270
271
272
273
274//Utility function that returns the detector resolution (in cm)
275//Global values are set in the Initialize procedure
276//
277//
278// - called by CircSectAvg.ipf, RectAnnulAvg.ipf, and ProtocolAsPanel.ipf
279//
280// fileStr is passed as TextRead[3]
281// detStr is passed as TextRead[9]
282//
283// *** as of Jan 2008, depricated. Now detector pixel sizes are read from the file header
284// rw[10] = x size (mm); rw[13] = y size (mm)
285//
286Function xDetectorPixelResolution(fileStr,detStr)
287        String fileStr,detStr
288       
289        Variable DDet
290        String instr=fileStr[1,3]       //filestr is "[NGnSANSn] " or "[NGnSANSnn]" (11 characters total)
291       
292        NVAR PixelResNG3_ILL = root:myGlobals:PixelResNG3_ILL           //pixel resolution in cm
293        NVAR PixelResNG5_ILL = root:myGlobals:PixelResNG5_ILL
294        NVAR PixelResNG7_ILL = root:myGlobals:PixelResNG7_ILL
295        NVAR PixelResNG3_ORNL = root:myGlobals:PixelResNG3_ORNL
296        NVAR PixelResNG5_ORNL = root:myGlobals:PixelResNG5_ORNL
297        NVAR PixelResNG7_ORNL = root:myGlobals:PixelResNG7_ORNL
298        NVAR PixelResDefault = root:myGlobals:PixelResDefault
299       
300        strswitch(instr)
301                case "NG3":
302                        if(cmpstr(detStr, "ILL   ") == 0 )
303                                DDet= PixelResNG3_ILL
304                        else
305                                DDet = PixelResNG3_ORNL //detector is ordella-type
306                        endif
307                        break
308                case "NG5":
309                        if(cmpstr(detStr, "ILL   ") == 0 )
310                                DDet= PixelResNG5_ILL
311                        else
312                                DDet = PixelResNG5_ORNL //detector is ordella-type
313                        endif
314                        break
315                case "NG7":
316                        if(cmpstr(detStr, "ILL   ") == 0 )
317                                DDet= PixelResNG7_ILL
318                        else
319                                DDet = PixelResNG7_ORNL //detector is ordella-type
320                        endif
321                        break
322                default:                                                       
323                        //return error?
324                        DDet = PixelResDefault  //0.5 cm, typical for new ORNL detectors
325        endswitch
326       
327        return(DDet)
328End
329
330//Utility function that returns the detector deadtime (in seconds)
331//Global values are set in the Initialize procedure
332//
333// - called by WorkFileUtils.ipf
334//
335// fileStr is passed as TextRead[3]
336// detStr is passed as TextRead[9]
337//
338Function DetectorDeadtime(fileStr,detStr)
339        String fileStr,detStr
340       
341        Variable deadtime
342        String instr=fileStr[1,3]       //filestr is "[NGnSANSn] " or "[NGnSANSnn]" (11 characters total)
343       
344        NVAR DeadtimeNG3_ILL = root:myGlobals:DeadtimeNG3_ILL           //pixel resolution in cm
345        NVAR DeadtimeNG5_ILL = root:myGlobals:DeadtimeNG5_ILL
346        NVAR DeadtimeNG7_ILL = root:myGlobals:DeadtimeNG7_ILL
347        NVAR DeadtimeNG3_ORNL = root:myGlobals:DeadtimeNG3_ORNL
348        NVAR DeadtimeNG5_ORNL = root:myGlobals:DeadtimeNG5_ORNL
349        NVAR DeadtimeNG7_ORNL = root:myGlobals:DeadtimeNG7_ORNL
350        NVAR DeadtimeDefault = root:myGlobals:DeadtimeDefault
351       
352        strswitch(instr)
353                case "NG3":
354                        if(cmpstr(detStr, "ILL   ") == 0 )
355                                deadtime= DeadtimeNG3_ILL
356                        else
357                                deadtime = DeadtimeNG3_ORNL     //detector is ordella-type
358                        endif
359                        break
360                case "NG5":
361                        if(cmpstr(detStr, "ILL   ") == 0 )
362                                deadtime= DeadtimeNG5_ILL
363                        else
364                                deadtime = DeadtimeNG5_ORNL     //detector is ordella-type
365                        endif
366                        break
367                case "NG7":
368                        if(cmpstr(detStr, "ILL   ") == 0 )
369                                deadtime= DeadtimeNG7_ILL
370                        else
371                                deadtime = DeadtimeNG7_ORNL     //detector is ordella-type
372                        endif
373                        break
374                default:                                                       
375                        //return error?
376                        deadtime = DeadtimeDefault      //1e-6 seconds, typical for new ORNL detectors
377        endswitch
378       
379        return(deadtime)
380End
381
382
383/////VAX filename/Run number parsing utilities
384//
385// a collection of uilities for processing vax filenames
386//and processing lists (especially for display in popup menus)
387//
388//required to correctly account for VAX supplied version numbers, which
389//may or may not be removed by the ftp utility
390//
391// - parses lists of run numbers into real filenames
392// - selects proper detector constants
393//
394//**************************
395//
396//given a filename of a SANS data filename of the form
397//TTTTTnnn.SAn_TTT_Txxx
398//returns the run number "nnn" as a number
399//returns -1 as an invalid file number
400//
401// called by several ipfs
402//
403//
404Function GetRunNumFromFile(item)
405        String item
406        Variable invalid = -1   //negative numbers are invalid
407        Variable num=-1
408       
409        //find the "dot"
410        String runStr=""
411        Variable pos = strsearch(item,".",0)
412        if(pos == -1)
413                //"dot" not found
414                return (invalid)
415        else
416                //found, get the three characters preceeding it
417                if (pos <=2)
418                        //not enough characters
419                        return (invalid)
420                else
421                        runStr = item[pos-3,pos-1]
422                        //convert to a number
423                        num = str2num(runStr)
424                        //if valid, return it
425                        if (num == NaN)
426                                //3 characters were not a number
427                                return (invalid)
428                        else
429                                //run was OK
430                                return (num)
431                        Endif
432                Endif
433        Endif
434End
435
436//given a filename of a SANS data filename of the form
437//TTTTTnnn.SAn_TTT_Txxx
438//returns the run number "nnn" as a STRING of THREE characters
439//returns "ABC" as an invalid file number
440//
441// local function to aid in locating files by run number
442//
443Function/S GetRunNumStrFromFile(item)
444        String item
445        String invalid = "ABC"  //"ABC" is not a valid run number, since it's text
446        Variable num=-1
447       
448        //find the "dot"
449        String runStr=""
450        Variable pos = strsearch(item,".",0)
451        if(pos == -1)
452                //"dot" not found
453                return (invalid)
454        else
455                //found, get the three characters preceeding it
456                if (pos <=2)
457                        //not enough characters
458                        return (invalid)
459                else
460                        runStr = item[pos-3,pos-1]
461                        return (runStr)
462                Endif
463        Endif
464End
465
466//returns a string containing the full path to the file containing the
467//run number "num". The null string is returned if no valid file can be found
468//the path "catPathName" used and is hard-wired, will abort if this path does not exist
469//the file returned will be a RAW SANS data file, other types of files are
470//filtered out.
471//
472// called by Buttons.ipf and Transmission.ipf, and locally by parsing routines
473//
474Function/S FindFileFromRunNumber(num)
475        Variable num
476       
477        String fullName="",partialName="",item=""
478        //get list of raw data files in folder that match "num" (add leading zeros)
479        if( (num>999) || (num<=0) )
480                //Print "error in  FindFileFromRunNumber(num), file number too large or too small"
481                Return ("")
482        Endif
483        //make a three character string of the run number
484        String numStr=""
485        if(num<10)
486                numStr = "00"+num2str(num)
487        else
488                if(num<100)
489                        numStr = "0"+num2str(num)
490                else
491                        numStr = num2str(num)
492                Endif
493        Endif
494        //Print "numstr = ",numstr
495       
496        //make sure that path exists
497        PathInfo catPathName
498        String path = S_path
499        if (V_flag == 0)
500                Abort "folder path does not exist - use Pick Path button"
501        Endif
502        String list="",newList="",testStr=""
503       
504        list = IndexedFile(catPathName,-1,"????")       //get all files in folder
505        //find (the) one with the number in the run # location in the name
506        Variable numItems,ii,runFound,isRAW
507        numItems = ItemsInList(list,";")                //get the new number of items in the list
508        ii=0
509        do
510                //parse through the list in this order:
511                // 1 - does item contain run number (as a string) "TTTTTnnn.SAn_XXX_Tyyy"
512                // 2 - exclude by isRaw? (to minimize disk access)
513                item = StringFromList(ii, list  ,";" )
514                if(strlen(item) != 0)
515                        //find the run number, if it exists as a three character string
516                        testStr = GetRunNumStrFromFile(item)
517                        runFound= cmpstr(numStr,testStr)        //compare the three character strings, 0 if equal
518                        if(runFound == 0)
519                                //the run Number was found
520                                //build valid filename
521                                partialName = FindValidFileName(item)
522                                if(strlen(partialName) != 0)            //non-null return from FindValidFileName()
523                                        fullName = path + partialName
524                                        //check if RAW, if so,this must be the file!
525                                        isRAW = CheckIfRawData(fullName)
526                                        if(isRaw)
527                                                //stop here
528                                                return(fullname)
529                                        Endif
530                                Endif
531                        Endif
532                Endif
533                ii+=1
534        while(ii<numItems)              //process all items in list
535        Return ("")     //null return if file not found in list
536End
537
538//function to test a binary file to see if it is a RAW binary SANS file
539//first checks the total bytes in the file (which for raw data is 33316 bytes)
540//**note that the "DIV" file will also show up as a raw file by the run field
541//should be listed in CAT/SHORT and in patch windows
542//
543//Function then checks the file fname (full path:file) for "RAW" run.type field
544//if not found, the data is not raw data and zero is returned
545//
546// called by many procedures (both external and local)
547//
548Function CheckIfRawData(fname)
549        String fname
550       
551        Variable refnum,totalBytes
552        String testStr=""
553       
554        Open/R/T="????TEXT" refNum as fname
555        //get the total number of bytes in the file
556        FStatus refNum
557        totalBytes = V_logEOF
558        //Print totalBytes
559        if(totalBytes < 100)
560                Close refNum
561                return(0)               //not a raw file
562        endif
563        FSetPos refNum,75
564        FReadLine/N=3 refNum,testStr
565        Close refNum
566       
567        if(totalBytes == 33316 && cmpstr(testStr,"RAW")==0)
568                //true, is raw data file
569                Return(1)
570        else
571                //some other file
572                Return(0)
573        Endif
574End
575
576//function to check the header of a raw data file (full path specified by fname)
577//checks the field of the x-position of the beamstop during data collection
578//if the x-position is more negative (farther to the left) than xTol(input)
579//the the beamstop is "out" and the file is a transmission run and not a scattering run
580//xtol typically set at -5 (cm) - trans runs have bs(x) at -10 to -15 cm
581// function returns 1 if beamstop is out, 0 if beamstop is in
582//
583// tolerance is set as a global value "root:myGlobals:BeamstopXTol"
584//
585// called by Transmission.ipf, CatVSTable.ipf, NSORT.ipf
586//
587Function isTransFile(fName)
588        String fname
589       
590        Variable refnum,xpos
591        NVAR xTol = root:myGlobals:BeamstopXTol
592       
593        //pos = 369, read one real value
594       
595        SetDataFolder root:
596        String GBLoadStr="GBLoadWave/O/N=tempGBwave/T={2,2}/J=2/W=1/Q"
597        String strToExecute=""
598        // 1 R*4 value
599        strToExecute = GBLoadStr + "/S=368/U=1" + "\"" + fname + "\""
600        Execute strToExecute
601        Wave w=$"root:tempGBWave0"
602        xPos = w[0]
603        KillWaves/Z w
604        //Print "xPos = ",xpos
605       
606        if(xpos<=xTol)
607                //xpos is farther left (more negative) than xtol (currently -5 cm)
608                Return(1)
609        else
610                //some other file
611                Return(0)
612        Endif
613End
614
615
616//function to remove all spaces from names when searching for filenames
617//the filename (as saved) will never have interior spaces (TTTTTnnn_AB _Bnnn)
618//but the text field in the header WILL, if less than 3 characters were used for the
619//user's initials, and can have leading spaces if prefix was less than 5 characters
620//
621//returns a string identical to the original string, except with the interior spaces removed
622//
623// local function for file name manipulation
624//
625Function/S RemoveAllSpaces(str)
626        String str
627       
628        String tempstr = str
629        Variable ii,spc,len             //should never be more than 2 or 3 trailing spaces in a filename
630        ii=0
631        do
632                len = strlen(tempStr)
633                spc = strsearch(tempStr," ",0)          //is the last character a space?
634                if (spc == -1)
635                        break           //no more spaces found, get out
636                endif
637                str = tempstr
638                tempStr = str[0,(spc-1)] + str[(spc+1),(len-1)] //remove the space from the string
639        While(1)        //should never be more than 2 or 3
640       
641        If(strlen(tempStr) < 1)
642                tempStr = ""            //be sure to return a null string if problem found
643        Endif
644       
645        //Print strlen(tempstr)
646       
647        Return(tempStr)
648               
649End
650
651
652//Function attempts to find valid filename from partial name by checking for
653// the existence of the file on disk.
654// - checks as is
655// - adds ";vers" for possible VAX files
656// - strips spaces
657// - permutations of upper/lowercase
658//
659// added 11/99 - uppercase and lowercase versions of the file are tried, if necessary
660// since from marquee, the filename field (textread[0]) must be used, and can be a mix of
661// upper/lowercase letters, while the filename on the server (should) be all caps
662// now makes repeated calls to ValidFileString()
663//
664// returns a valid filename (No path prepended) or a null string
665//
666// called by any functions, both external and local
667//
668Function/S FindValidFilename(partialName)
669        String PartialName
670       
671        String retStr=""
672       
673        //try name with no changes - to allow for ABS files that have spaces in the names 12APR04
674        retStr = ValidFileString(partialName)
675        if(cmpstr(retStr,"") !=0)
676                //non-null return
677                return(retStr)
678        Endif
679       
680        //if the partial name is derived from the file header, there can be spaces at the beginning
681        //or in the middle of the filename - depending on the prefix and initials used
682        //
683        //remove any leading spaces from the name before starting
684        partialName = RemoveAllSpaces(partialName)
685       
686        //try name with no spaces
687        retStr = ValidFileString(partialName)
688        if(cmpstr(retStr,"") !=0)
689                //non-null return
690                return(retStr)
691        Endif
692       
693        //try all UPPERCASE
694        partialName = UpperStr(partialName)
695        retStr = ValidFileString(partialName)
696        if(cmpstr(retStr,"") !=0)
697                //non-null return
698                return(retStr)
699        Endif
700       
701        //try all lowercase (ret null if failure)
702        partialName = LowerStr(partialName)
703        retStr = ValidFileString(partialName)
704        if(cmpstr(retStr,"") !=0)
705                //non-null return
706                return(retStr)
707        else
708                return(retStr)
709        Endif
710End
711
712// Function checks for the existence of a file
713// partialName;vers (to account for VAX filenaming conventions)
714// The partial name is tried first with no version number
715//
716// *** the PATH is hard-wired to catPathName (which is assumed to exist)
717// version numers up to ;10 are tried
718// only the "name;vers" is returned if successful. The path is not prepended
719//
720// local function
721//
722Function/S ValidFileString(partialName)
723        String partialName
724       
725        String tempName = "",msg=""
726        Variable ii,refnum
727       
728        ii=0
729        do
730                if(ii==0)
731                        //first pass, try the partialName
732                        tempName = partialName
733                        Open/Z/R/T="????TEXT"/P=catPathName refnum tempName     //Does open file (/Z flag)
734                        if(V_flag == 0)
735                                //file exists
736                                Close refnum            //YES needed,
737                                break
738                        endif
739                else
740                        tempName = partialName + ";" + num2str(ii)
741                        Open/Z/R/T="????TEXT"/P=catPathName refnum tempName
742                        if(V_flag == 0)
743                                //file exists
744                                Close refnum
745                                break
746                        endif
747                Endif
748                ii+=1
749                //print "ii=",ii
750        while(ii<11)
751        //go get the selected bits of information, using tempName, which exists
752        if(ii>=11)
753                //msg = partialName + " not found. is version number > 11?"
754                //DoAlert 0, msg
755                //PathInfo catPathName
756                //Print S_Path
757                Return ("")             //use null string as error condition
758        Endif
759       
760        Return (tempName)
761End
762
763//returns a string containing filename (WITHOUT the ;vers)
764//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
765//with the folders separated by colons
766//
767// called by MaskUtils.ipf, ProtocolAsPanel.ipf, WriteQIS.ipf
768//
769Function/S GetFileNameFromPathNoSemi(fullPath)
770        String fullPath
771       
772        Variable offset1,offset2
773        String filename=""
774        //String PartialPath
775        offset1 = 0
776        do
777                offset2 = StrSearch(fullPath, ":", offset1)
778                if (offset2 == -1)                              // no more colons ?
779                        fileName = FullPath[offset1,strlen(FullPath) ]
780                        //PartialPath = FullPath[0, offset1-1]
781                        break
782                endif
783                offset1 = offset2+1
784        while (1)
785       
786        //remove version number from name, if it's there - format should be: filename;N
787        filename =  StringFromList(0,filename,";")              //returns null if error
788       
789        Return filename
790End
791
792//returns a string containing filename (INCLUDING the ;vers)
793//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
794//with the folders separated by colons
795//
796// local, currently unused
797//
798Function/S GetFileNameFromPathKeepSemi(fullPath)
799        String fullPath
800       
801        Variable offset1,offset2
802        String filename
803        //String PartialPath
804        offset1 = 0
805        do
806                offset2 = StrSearch(fullPath, ":", offset1)
807                if (offset2 == -1)                              // no more colons ?
808                        fileName = FullPath[offset1,strlen(FullPath) ]
809                        //PartialPath = FullPath[0, offset1-1]
810                        break
811                endif
812                offset1 = offset2+1
813        while (1)
814       
815        //keep version number from name, if it's there - format should be: filename;N
816       
817        Return filename
818End
819
820//given the full path and filename (fullPath), strips the data path
821//(Mac-style, separated by colons) and returns this path
822//this partial path is the same string that would be returned from PathInfo, for example
823//
824// - allows the user to save to a different path than catPathName
825//
826// called by WriteQIS.ipf
827//
828Function/S GetPathStrFromfullName(fullPath)
829        String fullPath
830       
831        Variable offset1,offset2
832        //String filename
833        String PartialPath
834        offset1 = 0
835        do
836                offset2 = StrSearch(fullPath, ":", offset1)
837                if (offset2 == -1)                              // no more colons ?
838                        //fileName = FullPath[offset1,strlen(FullPath) ]
839                        PartialPath = FullPath[0, offset1-1]
840                        break
841                endif
842                offset1 = offset2+1
843        while (1)
844       
845        Return PartialPath
846End
847
848//given the VAX filename, pull off the first 8 characters to make a valid
849//file string that can be used for naming averaged 1-d files
850//
851// called by ProtocolAsPanel.ipf and Tile_2D.ipf
852//
853Function/S GetNameFromHeader(fullName)
854        String fullName
855        String temp, newName = ""
856        Variable spc,ii=0
857       
858        //filename is 20 characters NNNNNxxx.SAn_NNN_NNN
859        //want the first 8 characters, NNNNNxxx, then strip off any spaces at the beginning
860        //NNNNN was entered as less than 5 characters
861        //returns a null string if no name can be found
862        do
863                temp = fullname[ii,7]           //characters ii,7 of the name
864                spc = strsearch(temp," ",0)
865                if (spc == -1)
866                        break           //no more spaces found
867                endif
868                ii+=1
869        While(ii<8)
870       
871        If(strlen(temp) < 1)
872                newName = ""            //be sure to return a null string if problem found
873        else
874                newName = temp
875        Endif
876       
877        Return(newName)
878End
879
880//list (input) is a list, typically returned from IndexedFile()
881//which is semicolon-delimited, and may contain filenames from the VAX
882//that contain version numbers, where the version number appears as a separate list item
883//(and also as a non-existent file)
884//these numbers must be purged from the list, especially for display in a popup
885//or list processing of filenames
886//the function returns the list, cleaned of version numbers (up to 11)
887//raw data files will typically never have a version number other than 1.
888//
889// if there are no version numbers in the list, the input list is returned
890//
891// called by CatVSTable.ipf, NSORT.ipf, Transmission.ipf, WorkFileUtils.ipf
892//
893Function/S RemoveVersNumsFromList(list)
894        String list
895       
896        //get rid of version numbers first (up to 11)
897        Variable ii,num
898        String item
899        num = ItemsInList(list,";")
900        ii=1
901        do
902                item = num2str(ii)
903                list = RemoveFromList(item, list ,";" )
904                ii+=1
905        while(ii<12)
906       
907        return (list)
908End
909
910//input is a list of run numbers, and output is a list of filenames (not the full path)
911//*** input list must be COMMA delimited***
912//output is equivalent to selecting from the CAT table
913//if some or all of the list items are valid filenames, keep them...
914//if an error is encountered, notify of the offending element and return a null list
915//
916//output is COMMA delimited
917//
918// this routine is expecting that the "ask", "none" special cases are handled elsewhere
919//and not passed here
920//
921// called by Marquee.ipf, MultipleReduce.ipf, ProtocolAsPanel.ipf
922//
923Function/S ParseRunNumberList(list)
924        String list
925       
926        String newList="",item="",tempStr=""
927        Variable num,ii,runNum
928       
929        //expand number ranges, if any
930        list = ExpandNumRanges(list)
931       
932        num=itemsinlist(list,",")
933       
934        for(ii=0;ii<num;ii+=1)
935                //get the item
936                item = StringFromList(ii,list,",")
937                //is it already a valid filename?
938                tempStr=FindValidFilename(item) //returns filename if good, null if error
939                if(strlen(tempstr)!=0)
940                        //valid name, add to list
941                        //Print "it's a file"
942                        newList += tempStr + ","
943                else
944                        //not a valid name
945                        //is it a number?
946                        runNum=str2num(item)
947                        //print runnum
948                        if(numtype(runNum) != 0)
949                                //not a number -  maybe an error                       
950                                DoAlert 0,"List item "+item+" is not a valid run number or filename. Please enter a valid number or filename."
951                                return("")
952                        else
953                                //a run number or an error
954                                tempStr = GetFileNameFromPathNoSemi( FindFileFromRunNumber(runNum) )
955                                if(strlen(tempstr)==0)
956                                        //file not found, error
957                                        DoAlert 0,"List item "+item+" is not a valid run number. Please enter a valid number."
958                                        return("")
959                                else
960                                        newList += tempStr + ","
961                                endif
962                        endif
963                endif
964        endfor          //loop over all items in list
965       
966        return(newList)
967End
968
969//takes a comma delimited list that MAY contain number range, and
970//expands any range of run numbers into a comma-delimited list...
971//and returns the new list - if not a range, return unchanged
972//
973// local function
974//
975Function/S ExpandNumRanges(list)
976        String list
977       
978        String newList="",dash="-",item,str
979        Variable num,ii,hasDash
980       
981        num=itemsinlist(list,",")
982//      print num
983        for(ii=0;ii<num;ii+=1)
984                //get the item
985                item = StringFromList(ii,list,",")
986                //does it contain a dash?
987                hasDash = strsearch(item,dash,0)                //-1 if no dash found
988                if(hasDash == -1)
989                        //not a range, keep it in the list
990                        newList += item + ","
991                else
992                        //has a dash (so it's a range), expand (or add null)
993                        newList += ListFromDash(item)           
994                endif
995        endfor
996       
997        return newList
998End
999
1000//be sure to add a trailing comma to the return string...
1001//
1002// local function
1003//
1004Function/S ListFromDash(item)
1005        String item
1006       
1007        String numList="",loStr="",hiStr=""
1008        Variable lo,hi,ii
1009       
1010        loStr=StringFromList(0,item,"-")        //treat the range as a list
1011        hiStr=StringFromList(1,item,"-")
1012        lo=str2num(loStr)
1013        hi=str2num(hiStr)
1014        if( (numtype(lo) != 0) || (numtype(hi) !=0 ) || (lo > hi) )
1015                numList=""
1016                return numList
1017        endif
1018        for(ii=lo;ii<=hi;ii+=1)
1019                numList += num2str(ii) + ","
1020        endfor
1021       
1022        Return numList
1023End
1024
1025
1026////////Transmission
1027//******************
1028//lookup tables for attenuator transmissions
1029//NG3 and NG7 attenuators are physically different, so the transmissions are slightly different
1030//NG1 - (8m SANS) is not supported
1031//
1032// new calibration done June 2007, John Barker
1033//
1034Proc MakeNG3AttenTable()
1035
1036        NewDataFolder/O root:myGlobals:Attenuators
1037        //do explicitly to avoid data folder problems, redundant, but it must work without fail
1038        Variable num=10         //10 needed for tables after June 2007
1039
1040        Make/O/N=(num) root:myGlobals:Attenuators:ng3att0
1041        Make/O/N=(num) root:myGlobals:Attenuators:ng3att1
1042        Make/O/N=(num) root:myGlobals:Attenuators:ng3att2
1043        Make/O/N=(num) root:myGlobals:Attenuators:ng3att3
1044        Make/O/N=(num) root:myGlobals:Attenuators:ng3att4
1045        Make/O/N=(num) root:myGlobals:Attenuators:ng3att5
1046        Make/O/N=(num) root:myGlobals:Attenuators:ng3att6
1047        Make/O/N=(num) root:myGlobals:Attenuators:ng3att7
1048        Make/O/N=(num) root:myGlobals:Attenuators:ng3att8
1049        Make/O/N=(num) root:myGlobals:Attenuators:ng3att9
1050        Make/O/N=(num) root:myGlobals:Attenuators:ng3att10
1051       
1052        //each wave has 10 elements, the transmission of att# at the wavelengths
1053        //lambda = 4,5,6,7,8,10,12,14,17,20 (4 A and 20 A are extrapolated values)
1054        Make/O/N=(num) root:myGlobals:Attenuators:ng3lambda={4,5,6,7,8,10,12,14,17,20}
1055       
1056        // new calibration done June 2007, John Barker
1057        root:myGlobals:Attenuators:ng3att0 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
1058        root:myGlobals:Attenuators:ng3att1 = {0.444784,0.419,0.3935,0.3682,0.3492,0.3132,0.2936,0.2767,0.2477,0.22404}
1059        root:myGlobals:Attenuators:ng3att2 = {0.207506,0.1848,0.1629,0.1447,0.1292,0.1056,0.09263,0.08171,0.06656,0.0546552}
1060        root:myGlobals:Attenuators:ng3att3 = {0.092412,0.07746,0.06422,0.05379,0.04512,0.03321,0.02707,0.02237,0.01643,0.0121969}
1061        root:myGlobals:Attenuators:ng3att4 = {0.0417722,0.03302,0.02567,0.02036,0.01604,0.01067,0.00812,0.006316,0.00419,0.00282411}
1062        root:myGlobals:Attenuators:ng3att5 = {0.0187129,0.01397,0.01017,0.007591,0.005668,0.003377,0.002423,0.001771,0.001064,0.000651257}
1063        root:myGlobals:Attenuators:ng3att6 = {0.00851048,0.005984,0.004104,0.002888,0.002029,0.001098,0.0007419,0.0005141,0.000272833,0.000150624}
1064        root:myGlobals:Attenuators:ng3att7 = {0.00170757,0.001084,0.0006469,0.0004142,0.0002607,0.0001201,7.664e-05,4.06624e-05,1.77379e-05,7.30624e-06}
1065        root:myGlobals:Attenuators:ng3att8 = {0.000320057,0.0001918,0.0001025,6.085e-05,3.681e-05,1.835e-05,6.74002e-06,3.25288e-06,1.15321e-06,3.98173e-07}
1066        root:myGlobals:Attenuators:ng3att9 = {6.27682e-05,3.69e-05,1.908e-05,1.196e-05,8.738e-06,6.996e-06,6.2901e-07,2.60221e-07,7.49748e-08,2.08029e-08}
1067        root:myGlobals:Attenuators:ng3att10 = {1.40323e-05,8.51e-06,5.161e-06,4.4e-06,4.273e-06,1.88799e-07,5.87021e-08,2.08169e-08,4.8744e-09,1.08687e-09}
1068 
1069  //old tables, pre-June 2007
1070//      Make/O/N=9 root:myGlobals:Attenuators:ng3lambda={5,6,7,8,10,12,14,17,20}
1071//      root:myGlobals:Attenuators:ng3att0 = {1, 1, 1, 1, 1, 1, 1, 1,1 }
1072//      root:myGlobals:Attenuators:ng3att1 = {0.421, 0.394, 0.371, 0.349, 0.316, 0.293, 0.274, 0.245,0.220}
1073//      root:myGlobals:Attenuators:ng3att2 = {0.187, 0.164, 0.145, 0.130, 0.106, 0.0916, 0.0808, 0.0651,0.0531}
1074//      root:myGlobals:Attenuators:ng3att3 = {0.0777, 0.0636, 0.0534, 0.0446, 0.0330, 0.0262, 0.0217, 0.0157 ,0.0116}
1075//      root:myGlobals:Attenuators:ng3att4 = {0.0328, 0.0252, 0.0195, 0.0156, 0.0104, 7.68e-3, 5.98e-3, 3.91e-3,0.00262}
1076//      root:myGlobals:Attenuators:ng3att5 = {0.0139, 9.94e-3, 7.34e-3, 5.44e-3, 3.29e-3, 2.25e-3, 1.66e-3, 9.95e-4, 6.12e-4}
1077//      root:myGlobals:Attenuators:ng3att6 = {5.95e-3, 3.97e-3, 2.77e-3, 1.95e-3, 1.06e-3, 6.81e-4, 4.71e-4, 2.59e-4 , 1.45e-4}
1078//      root:myGlobals:Attenuators:ng3att7 = {1.07e-3, 6.24e-4, 3.90e-4, 2.44e-4, 1.14e-4, 6.55e-5, 4.10e-5, 1.64e-5 , 7.26e-6}
1079//      root:myGlobals:Attenuators:ng3att8 = {1.90e-4, 9.84e-5, 5.60e-5, 3.25e-5, 1.55e-5, 6.60e-6, 3.42e-6, 1.04e-6 , 3.48e-7}
1080//      root:myGlobals:Attenuators:ng3att9 = {3.61e-5, 1.74e-5, 9.90e-6, 6.45e-6, 2.35e-6, 6.35e-7, 2.86e-7, 6.61e-8 , 1.73e-8}
1081//      root:myGlobals:Attenuators:ng3att10 = {7.60e-6, 3.99e-6, 2.96e-6, 2.03e-6, 3.34e-7, 6.11e-8, 2.39e-8, 4.19e-9 , 8.60e-10}
1082
1083End
1084
1085// new calibration done June 2007, John Barker
1086Proc MakeNG7AttenTable()
1087
1088        NewDataFolder/O root:myGlobals:Attenuators
1089       
1090        Variable num=10         //10 needed for tables after June 2007
1091       
1092        Make/O/N=(num) root:myGlobals:Attenuators:ng7att0
1093        Make/O/N=(num) root:myGlobals:Attenuators:ng7att1
1094        Make/O/N=(num) root:myGlobals:Attenuators:ng7att2
1095        Make/O/N=(num) root:myGlobals:Attenuators:ng7att3
1096        Make/O/N=(num) root:myGlobals:Attenuators:ng7att4
1097        Make/O/N=(num) root:myGlobals:Attenuators:ng7att5
1098        Make/O/N=(num) root:myGlobals:Attenuators:ng7att6
1099        Make/O/N=(num) root:myGlobals:Attenuators:ng7att7
1100        Make/O/N=(num) root:myGlobals:Attenuators:ng7att8
1101        Make/O/N=(num) root:myGlobals:Attenuators:ng7att9
1102        Make/O/N=(num) root:myGlobals:Attenuators:ng7att10
1103       
1104        //NG7 wave has 10 elements, the transmission of att# at the wavelengths
1105        //lambda =4, 5,6,7,8,10,12,14,17,20
1106        // note that some of the higher attenuations and ALL of the 4 A and 20A data is interpolated
1107        // none of these values are expected to be used in reality since the flux would be too low in practice
1108        Make/O/N=(num) root:myGlobals:Attenuators:ng7lambda={4,5,6,7,8,10,12,14,17,20}
1109
1110// New calibration, June 2007, John Barker
1111        root:myGlobals:Attenuators:ng7att0 = {1, 1, 1, 1, 1, 1, 1, 1 ,1,1}     
1112        root:myGlobals:Attenuators:ng7att1 = {0.448656,0.4192,0.3925,0.3661,0.3458,0.3098,0.2922,0.2738,0.2544,0.251352}
1113        root:myGlobals:Attenuators:ng7att2 = {0.217193,0.1898,0.1682,0.148,0.1321,0.1076,0.0957,0.08485,0.07479,0.0735965}
1114        root:myGlobals:Attenuators:ng7att3 = {0.098019,0.07877,0.06611,0.05429,0.04548,0.03318,0.02798,0.0234,0.02004,0.0202492}
1115        root:myGlobals:Attenuators:ng7att4 = {0.0426904,0.03302,0.02617,0.02026,0.0158,0.01052,0.008327,0.006665,0.005745,0.00524807}
1116        root:myGlobals:Attenuators:ng7att5 = {0.0194353,0.01398,0.01037,0.0075496,0.005542,0.003339,0.002505,0.001936,0.001765,0.00165959}
1117        root:myGlobals:Attenuators:ng7att6 = {0.00971666,0.005979,0.004136,0.002848,0.001946,0.001079,0.0007717,0.000588,0.000487337,0.000447713}
1118        root:myGlobals:Attenuators:ng7att7 = {0.00207332,0.001054,0.0006462,0.0003957,0.0002368,0.0001111,7.642e-05,4.83076e-05,3.99401e-05,3.54814e-05}
1119        root:myGlobals:Attenuators:ng7att8 = {0.000397173,0.0001911,0.0001044,5.844e-05,3.236e-05,1.471e-05,6.88523e-06,4.06541e-06,3.27333e-06,2.81838e-06}
1120        root:myGlobals:Attenuators:ng7att9 = {9.43625e-05,3.557e-05,1.833e-05,1.014e-05,6.153e-06,1.64816e-06,6.42353e-07,3.42132e-07,2.68269e-07,2.2182e-07}
1121        root:myGlobals:Attenuators:ng7att10 = {2.1607e-05,7.521e-06,2.91221e-06,1.45252e-06,7.93451e-07,1.92309e-07,5.99279e-08,2.87928e-08,2.19862e-08,1.7559e-08}
1122
1123// Pre-June 2007 calibration values - do not use these anymore 
1124////    root:myGlobals:Attenuators:ng7att0 = {1, 1, 1, 1, 1, 1, 1, 1 ,1}
1125////    root:myGlobals:Attenuators:ng7att1 = {0.418, 0.393, 0.369, 0.347, 0.313, 0.291, 0.271, 0.244, 0.219 }
1126////    root:myGlobals:Attenuators:ng7att2 = {0.189, 0.167, 0.148, 0.132, 0.109, 0.0945, 0.0830, 0.0681, 0.0560}
1127////    root:myGlobals:Attenuators:ng7att3 = {0.0784, 0.0651, 0.0541, 0.0456, 0.0340, 0.0273, 0.0223, 0.0164 , 0.0121}
1128////    root:myGlobals:Attenuators:ng7att4 = {0.0328, 0.0256, 0.0200, 0.0159, 0.0107, 7.98e-3, 6.14e-3, 4.09e-3 , 0.00274}
1129////    root:myGlobals:Attenuators:ng7att5 = {0.0139, 0.0101, 7.43e-3, 5.58e-3, 3.42e-3, 2.36e-3, 1.70e-3, 1.03e-3 , 6.27e-4}
1130////    root:myGlobals:Attenuators:ng7att6 = {5.90e-3, 4.07e-3, 2.79e-3, 1.99e-3, 1.11e-3, 7.13e-4, 4.91e-4, 2.59e-4 , 1.42e-4}
1131////    root:myGlobals:Attenuators:ng7att7 = {1.04e-3, 6.37e-4, 3.85e-4, 2.46e-4, 1.16e-4, 6.86e-5, 4.10e-5, 1.64e-5 ,7.02e-6}
1132////    root:myGlobals:Attenuators:ng7att8 = {1.90e-4, 1.03e-4, 5.71e-5, 3.44e-5, 1.65e-5, 6.60e-6, 3.42e-6, 1.04e-6 , 3.48e-7}
1133////    root:myGlobals:Attenuators:ng7att9 = {3.58e-5, 1.87e-5, 1.05e-5, 7.00e-6, 2.35e-6, 6.35e-7, 2.86e-7, 6.61e-8 , 1.73e-8}
1134////    root:myGlobals:Attenuators:ng7att10 = {7.76e-6, 4.56e-6, 3.25e-6, 2.03e-6, 3.34e-7, 6.11e-8, 2.39e-8, 4.19e-9, 8.60e-10}
1135End
1136
1137//returns the transmission of the attenuator (at NG3) given the attenuator number
1138//which must be an integer(to select the wave) and given the wavelength.
1139//the wavelength may be any value between 4 and 20 (A), and is interpolated
1140//between calibrated wavelengths for a given attenuator
1141//
1142//
1143Function LookupAttenNG3(lambda,attenNo)
1144        Variable lambda, attenNo
1145       
1146        Variable trans
1147        String attStr="root:myGlobals:Attenuators:ng3att"+num2str(trunc(attenNo))
1148        String lamStr = "root:myGlobals:Attenuators:ng3lambda"
1149       
1150        if(attenNo == 0)
1151                return (1)              //no attenuation, return trans == 1
1152        endif
1153       
1154        if( (lambda < 4) || (lambda > 20 ) )
1155                Abort "Wavelength out of calibration range (4,20). You must manually enter the absolute parameters"
1156        Endif
1157       
1158        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) )
1159                Execute "MakeNG3AttenTable()"
1160        Endif
1161        //just in case creating the tables fails....
1162        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) )
1163                Abort "Attenuator lookup waves could not be found. You must manually enter the absolute parameters"
1164        Endif
1165       
1166        //lookup the value by interpolating the wavelength
1167        //the attenuator must always be an integer
1168        Wave att = $attStr
1169        Wave lam = $lamstr
1170        trans = interp(lambda,lam,att)
1171       
1172//      Print "trans = ",trans
1173       
1174        return trans
1175End
1176
1177//returns the transmission of the attenuator (at NG7) given the attenuator number
1178//which must be an integer(to select the wave) and given the wavelength.
1179//the wavelength may be any value between 4 and 20 (A), and is interpolated
1180//between calibrated wavelengths for a given attenuator
1181//
1182// this set of tables is also used for NG5 (NG1) SANS instrument - as the attenuator has never been calibrated
1183//
1184// local function
1185//
1186Function LookupAttenNG7(lambda,attenNo)
1187        Variable lambda, attenNo
1188       
1189        Variable trans
1190        String attStr="root:myGlobals:Attenuators:ng7att"+num2str(trunc(attenNo))
1191        String lamStr = "root:myGlobals:Attenuators:ng7lambda"
1192       
1193        if(attenNo == 0)
1194                return (1)              //no attenuation, return trans == 1
1195        endif
1196       
1197        if( (lambda < 4) || (lambda > 20 ) )
1198                Abort "Wavelength out of calibration range (4,20). You must manually enter the absolute parameters"
1199        Endif
1200       
1201        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) )
1202                Execute "MakeNG7AttenTable()"
1203        Endif
1204        //just in case creating the tables fails....
1205        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) )
1206                Abort "Attenuator lookup waves could not be found. You must manually enter the absolute parameters"
1207        Endif
1208       
1209        //lookup the value by interpolating the wavelength
1210        //the attenuator must always be an integer
1211        Wave att = $attStr
1212        Wave lam = $lamstr
1213        trans = interp(lambda,lam,att)
1214       
1215        //Print "trans = ",trans
1216       
1217        return trans
1218
1219End
1220
1221//returns the proper attenuation factor based on the instrument (NG3, NG5, or NG7)
1222//NG5 values are taken from the NG7 tables (there is very little difference in the
1223//values, and NG5 attenuators have not been calibrated (as of 8/01)
1224//
1225// filestr is passed from TextRead[3] = the default directory
1226// lam is passed from RealsRead[26]
1227// AttenNo is passed from ReaslRead[3]
1228//
1229// Attenuation factor as defined here is <= 1
1230//
1231// ORNL can pass ("",1,attenuationFactor) and have this function simply
1232// spit back the attenuationFactor (that was read into rw[3])
1233//
1234// called by Correct.ipf, ProtocolAsPanel.ipf, Transmission.ipf
1235//
1236Function AttenuationFactor(fileStr,lam,attenNo)
1237        String fileStr
1238        Variable lam,attenNo
1239       
1240        Variable attenFactor=1,loc
1241        String instr=fileStr[1,3]       //filestr is "[NGnSANSn] " or "[NGnSANSnn]" (11 characters total)
1242       
1243        strswitch(instr)
1244                case "NG3":
1245                        attenFactor = LookupAttenNG3(lam,attenNo)
1246                        break
1247                case "NG5":
1248                        //using NG7 lookup Table
1249                        attenFactor = LookupAttenNG7(lam,attenNo)
1250                        break
1251                case "NG7":
1252                        attenFactor = LookupAttenNG7(lam,attenNo)
1253                        break
1254                default:                                                       
1255                        //return error?
1256                        attenFactor=1
1257        endswitch
1258//      print "instr, lambda, attenNo,attenFactor = ",instr,lam,attenNo,attenFactor
1259        return(attenFactor)
1260End
1261
1262//function called by the popups to get a file list of data that can be sorted
1263// this procedure simply removes the raw data files from the string - there
1264//can be lots of other junk present, but this is very fast...
1265//
1266// could also use the alternate procedure of keeping only file with the proper extension
1267//
1268// another possibility is to get a listing of the text files, but is unreliable on
1269// Windows, where the data file must be .txt (and possibly OSX)
1270//
1271// called by FIT_Ops.ipf, NSORT.ipf, PlotUtils.ipf
1272//
1273Function/S ReducedDataFileList(ctrlName)
1274        String ctrlName
1275
1276        String list="",newList="",item=""
1277        Variable num,ii
1278       
1279        //check for the path
1280        PathInfo catPathName
1281        if(V_Flag==0)
1282                DoAlert 0, "Data path does not exist - pick the data path from the button on the main panel"
1283                Return("")
1284        Endif
1285       
1286        list = IndexedFile(catpathName,-1,"????")
1287        num=ItemsInList(list,";")
1288        //print "num = ",num
1289        for(ii=(num-1);ii>=0;ii-=1)
1290                item = StringFromList(ii, list  ,";")
1291                //simply remove all that are not raw data files (SA1 SA2 SA3)
1292                if( !stringmatch(item,"*.SA1*") && !stringmatch(item,"*.SA2*") && !stringmatch(item,"*.SA3*") )
1293                        if( !stringmatch(item,".*") && !stringmatch(item,"*.pxp") && !stringmatch(item,"*.DIV"))                //eliminate mac "hidden" files, pxp, and div files
1294                                newlist += item + ";"
1295                        endif
1296                endif
1297        endfor
1298        //remove VAX version numbers
1299        newList = RemoveVersNumsFromList(newList)
1300        //sort
1301        newList = SortList(newList,";",0)
1302
1303        return newlist
1304End
1305
1306// returns a list of raw data files in the catPathName directory on disk
1307// - list is SEMICOLON-delimited
1308//
1309// does it the "cheap" way, simply finding the ".SAn" in the file name
1310// = does not check for proper byte length.
1311//
1312// called by PatchFiles.ipf, Tile_2D.ipf
1313//
1314Function/S GetRawDataFileList()
1315       
1316        //make sure that path exists
1317        PathInfo catPathName
1318        if (V_flag == 0)
1319                Abort "Folder path does not exist - use Pick Path button on Main Panel"
1320        Endif
1321       
1322        String list=IndexedFile(catPathName,-1,"????")
1323        String newList="",item=""
1324        Variable num=ItemsInList(list,";"),ii
1325        for(ii=0;ii<num;ii+=1)
1326                item = StringFromList(ii, list  ,";")
1327                if( stringmatch(item,"*.sa1*") )
1328                        newlist += item + ";"
1329                endif
1330                if( stringmatch(item,"*.sa2*") )
1331                        newlist += item + ";"
1332                endif
1333                if( stringmatch(item,"*.sa3*") )
1334                        newlist += item + ";"
1335                endif
1336                //print "ii=",ii
1337        endfor
1338        newList = SortList(newList,";",0)
1339        return(newList)
1340End
Note: See TracBrowser for help on using the repository browser.