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

Last change on this file since 886 was 886, checked in by srkline, 10 years ago

Changes to SASCALC and other locations in the code that identify the instrument from the account name that is stored in the file header. New designation of NGA for the 10-m SANS, and NGB is reserved for the NG3 30-m SANS when it is moved into the new guide hall. Changes to incorporate the 10m SANS are functional, but INCOMPLETE since many of the instrument details have not been filled in yet (they haven't been measured yet).

File size: 65.5 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma version=5.0
3#pragma IgorVersion=6.1
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:PixelResNGA_ORNL = 0.5
35
36        Variable/G root:myGlobals:PixelResDefault = 0.5
37       
38        Variable/G root:myGlobals:DeadtimeNG3_ILL = 3.0e-6              //deadtime in seconds
39        Variable/G root:myGlobals:DeadtimeNG5_ILL = 3.0e-6
40        Variable/G root:myGlobals:DeadtimeNG7_ILL = 3.0e-6
41        Variable/G root:myGlobals:DeadtimeNGA_ILL = 3.0e-6              // fictional
42        Variable/G root:myGlobals:DeadtimeNG3_ORNL_VAX = 3.4e-6         //pre - 23-JUL-2009 used VAX
43        Variable/G root:myGlobals:DeadtimeNG3_ORNL_ICE = 1.5e-6         //post - 23-JUL-2009 used ICE
44        Variable/G root:myGlobals:DeadtimeNG5_ORNL = 0.6e-6                     //as of 9 MAY 2002
45        Variable/G root:myGlobals:DeadtimeNG7_ORNL_VAX = 3.4e-6         //pre 25-FEB-2010 used VAX
46        Variable/G root:myGlobals:DeadtimeNG7_ORNL_ICE = 2.3e-6         //post 25-FEB-2010 used ICE
47//      Variable/G root:myGlobals:DeadtimeNGA_ORNL_ICE = 1.0e-6         //not yet measured for NGA (10m)
48        Variable/G root:myGlobals:DeadtimeDefault = 3.4e-6
49       
50        //new 11APR07
51        Variable/G root:myGlobals:BeamstopXTol = -8                     // (cm) is BS Xpos is -5 cm or less, it's a trans measurement
52        // sample aperture offset is NOT stored in the VAX header, but it should be
53        // - when it is, remove the global and write an accessor AND make a place for
54        // it in the RealsRead
55        Variable/G root:myGlobals:apOff = 5.0                           // (cm) distance from sample aperture to sample position
56
57End
58
59
60//**********************
61// Resolution calculation - used by the averaging routines
62// to calculate the resolution function at each q-value
63// - the return value is not used
64//
65// equivalent to John's routine on the VAX Q_SIGMA_AVE.FOR
66// Incorporates eqn. 3-15 from J. Appl. Cryst. (1995) v. 28 p105-114
67//
68// - 21 MAR 07 uses projected BS diameter on the detector
69// - APR 07 still need to add resolution with lenses. currently there is no flag in the
70//          raw data header to indicate the presence of lenses.
71//
72// - Aug 07 - added input to switch calculation based on lenses (==1 if in)
73//
74// - called by CircSectAvg.ipf and RectAnnulAvg.ipf
75//
76// passed values are read from RealsRead
77// except DDet and apOff, which are set from globals before passing
78//
79//
80Function/S getResolution(inQ,lambda,lambdaWidth,DDet,apOff,S1,S2,L1,L2,BS,del_r,usingLenses,SigmaQ,QBar,fSubS)
81        Variable inQ, lambda, lambdaWidth, DDet, apOff, S1, S2, L1, L2, BS, del_r,usingLenses
82        Variable &fSubS, &QBar, &SigmaQ         //these are the output quantities at the input Q value
83       
84        //lots of calculation variables
85        Variable a2, q_small, lp, v_lambda, v_b, v_d, vz, yg, v_g
86        Variable r0, delta, inc_gamma, fr, fv, rmd, v_r1, rm, v_r
87
88        //Constants
89        Variable vz_1 = 3.956e5         //velocity [cm/s] of 1 A neutron
90        Variable g = 981.0                              //gravity acceleration [cm/s^2]
91
92        String results
93        results ="Failure"
94
95        S1 *= 0.5*0.1                   //convert to radius and [cm]
96        S2 *= 0.5*0.1
97
98        L1 *= 100.0                     // [cm]
99        L1 -= apOff                             //correct the distance
100
101        L2 *= 100.0
102        L2 += apOff
103        del_r *= 0.1                            //width of annulus, convert mm to [cm]
104       
105        BS *= 0.5*0.1                   //nominal BS diameter passed in, convert to radius and [cm]
106        // 21 MAR 07 SRK - use the projected BS diameter, based on a point sample aperture
107        Variable LB
108        LB = 20.1 + 1.61*BS                     //distance in cm from beamstop to anode plane (empirical)
109        BS = bs + bs*lb/(l2-lb)         //adjusted diameter of shadow from parallax
110       
111        //Start resolution calculation
112        a2 = S1*L2/L1 + S2*(L1+L2)/L1
113        q_small = 2.0*Pi*(BS-a2)*(1.0-lambdaWidth)/(lambda*L2)
114        lp = 1.0/( 1.0/L1 + 1.0/L2)
115
116        v_lambda = lambdaWidth^2/6.0
117       
118//      if(usingLenses==1)                      //SRK 2007
119        if(usingLenses != 0)                    //SRK 2008 allows for the possibility of different numbers of lenses in header
120                v_b = 0.25*(S1*L2/L1)^2 +0.25*(2/3)*(lambdaWidth/lambda)^2*(S2*L2/lp)^2         //correction to 2nd term
121        else
122                v_b = 0.25*(S1*L2/L1)^2 +0.25*(S2*L2/lp)^2              //original form
123        endif
124       
125        v_d = (DDet/2.3548)^2 + del_r^2/12.0
126        vz = vz_1 / lambda
127        yg = 0.5*g*L2*(L1+L2)/vz^2
128        v_g = 2.0*(2.0*yg^2*v_lambda)                                   //factor of 2 correction, B. Hammouda, 2007
129
130        r0 = L2*tan(2.0*asin(lambda*inQ/(4.0*Pi) ))
131        delta = 0.5*(BS - r0)^2/v_d
132
133        if (r0 < BS)
134                inc_gamma=exp(gammln(1.5))*(1-gammp(1.5,delta))
135        else
136                inc_gamma=exp(gammln(1.5))*(1+gammp(1.5,delta))
137        endif
138
139        fSubS = 0.5*(1.0+erf( (r0-BS)/sqrt(2.0*v_d) ) )
140        if (fSubS <= 0.0)
141                fSubS = 1.e-10
142        endif
143        fr = 1.0 + sqrt(v_d)*exp(-1.0*delta) /(r0*fSubS*sqrt(2.0*Pi))
144        fv = inc_gamma/(fSubS*sqrt(Pi)) - r0^2*(fr-1.0)^2/v_d
145
146        rmd = fr*r0
147        v_r1 = v_b + fv*v_d +v_g
148
149        rm = rmd + 0.5*v_r1/rmd
150        v_r = v_r1 - 0.5*(v_r1/rmd)^2
151        if (v_r < 0.0)
152                v_r = 0.0
153        endif
154        QBar = (4.0*Pi/lambda)*sin(0.5*atan(rm/L2))
155        SigmaQ = QBar*sqrt(v_r/rmd^2 +v_lambda)
156
157
158// more readable method for calculating the variance in Q
159// EXCEPT - this is calculated for Qo, NOT qBar
160// (otherwise, they are nearly equivalent, except for close to the beam stop)
161//      Variable kap,a_val,a_val_l2,m_h
162//      g = 981.0                               //gravity acceleration [cm/s^2]
163//      m_h     = 252.8                 // m/h [=] s/cm^2
164//     
165//      kap = 2*pi/lambda
166//      a_val = L2*(L1+L2)*g/2*(m_h)^2
167//      a_val_L2 = a_val/L2*1e-16               //convert 1/cm^2 to 1/A^2
168//
169//      sigmaQ = 0
170//      sigmaQ = 3*(S1/L1)^2
171//     
172//      if(usingLenses != 0)
173//              sigmaQ += 2*(S2/lp)^2*(lambdaWidth)^2   //2nd term w/ lenses
174//      else   
175//              sigmaQ += 2*(S2/lp)^2                                           //2nd term w/ no lenses
176//      endif
177//     
178//      sigmaQ += (del_r/L2)^2
179//      sigmaQ += 2*(r0/L2)^2*(lambdaWidth)^2
180//      sigmaQ += 4*(a_val_l2)^2*lambda^4*(lambdaWidth)^2
181//     
182//      sigmaQ *= kap^2/12
183//      sigmaQ = sqrt(sigmaQ)
184
185
186        results = "success"
187        Return results
188End
189
190
191//
192//**********************
193// 2D resolution function calculation - ***NOT*** in terms of X and Y
194// but written in terms of Parallel and perpendicular to the Q vector at each point
195//
196// -- it is more naturally written this way since the 2D function is an ellipse with its major
197// axis pointing in the direction of Q_parallel. Hence there is no way to properly define the
198// elliptical gaussian in terms of sigmaX and sigmaY
199//
200// For a full description of the gravity effect on the resolution, see:
201//
202//      "The effect of gravity on the resolution of small-angle neutron diffraction peaks"
203//      D.F.R Mildner, J.G. Barker & S.R. Kline J. Appl. Cryst. (2011). 44, 1127-1129.
204//      [ doi:10.1107/S0021889811033322 ]
205//
206//              2/17/12 SRK
207//              NOTE: the first 2/3 of this code is the 1D code, copied here just to have the beam stop
208//                              calculation here, if I decide to implement it. The real calculation is all at the
209//                              bottom and is quite compact
210//
211//
212//
213//
214// - 21 MAR 07 uses projected BS diameter on the detector
215// - APR 07 still need to add resolution with lenses. currently there is no flag in the
216//          raw data header to indicate the presence of lenses.
217//
218// - Aug 07 - added input to switch calculation based on lenses (==1 if in)
219//
220// passed values are read from RealsRead
221// except DDet and apOff, which are set from globals before passing
222//
223// phi is the azimuthal angle, CCW from +x axis
224// r_dist is the real-space distance from ctr of detector to QxQy pixel location
225//
226// MAR 2011 - removed the del_r terms, they don't apply since no bining is done to the 2D data
227//
228Function/S get2DResolution(inQ,phi,lambda,lambdaWidth,DDet,apOff,S1,S2,L1,L2,BS,del_r,usingLenses,r_dist,SigmaQX,SigmaQY,fSubS)
229        Variable inQ, phi,lambda, lambdaWidth, DDet, apOff, S1, S2, L1, L2, BS, del_r,usingLenses,r_dist
230        Variable &SigmaQX,&SigmaQY,&fSubS               //these are the output quantities at the input Q value
231       
232        //lots of calculation variables
233        Variable a2, lp, v_lambda, v_b, v_d, vz, yg, v_g
234        Variable r0, delta, inc_gamma, fr, fv, rmd, v_r1, rm, v_r
235
236        //Constants
237        Variable vz_1 = 3.956e5         //velocity [cm/s] of 1 A neutron
238        Variable g = 981.0                              //gravity acceleration [cm/s^2]
239        Variable m_h    = 252.8                 // m/h [=] s/cm^2
240
241        String results
242        results ="Failure"
243
244        S1 *= 0.5*0.1                   //convert to radius and [cm]
245        S2 *= 0.5*0.1
246
247        L1 *= 100.0                     // [cm]
248        L1 -= apOff                             //correct the distance
249
250        L2 *= 100.0
251        L2 += apOff
252        del_r *= 0.1                            //width of annulus, convert mm to [cm]
253       
254        BS *= 0.5*0.1                   //nominal BS diameter passed in, convert to radius and [cm]
255        // 21 MAR 07 SRK - use the projected BS diameter, based on a point sample aperture
256        Variable LB
257        LB = 20.1 + 1.61*BS                     //distance in cm from beamstop to anode plane (empirical)
258        BS = bs + bs*lb/(l2-lb)         //adjusted diameter of shadow from parallax
259       
260        //Start resolution calculation
261        a2 = S1*L2/L1 + S2*(L1+L2)/L1
262        lp = 1.0/( 1.0/L1 + 1.0/L2)
263
264        v_lambda = lambdaWidth^2/6.0
265       
266//      if(usingLenses==1)                      //SRK 2007
267        if(usingLenses != 0)                    //SRK 2008 allows for the possibility of different numbers of lenses in header
268                v_b = 0.25*(S1*L2/L1)^2 +0.25*(2/3)*(lambdaWidth/lambda)^2*(S2*L2/lp)^2         //correction to 2nd term
269        else
270                v_b = 0.25*(S1*L2/L1)^2 +0.25*(S2*L2/lp)^2              //original form
271        endif
272       
273        v_d = (DDet/2.3548)^2 + del_r^2/12.0
274        vz = vz_1 / lambda
275        yg = 0.5*g*L2*(L1+L2)/vz^2
276        v_g = 2.0*(2.0*yg^2*v_lambda)                                   //factor of 2 correction, B. Hammouda, 2007
277
278        r0 = L2*tan(2.0*asin(lambda*inQ/(4.0*Pi) ))
279        delta = 0.5*(BS - r0)^2/v_d
280
281        if (r0 < BS)
282                inc_gamma=exp(gammln(1.5))*(1-gammp(1.5,delta))
283        else
284                inc_gamma=exp(gammln(1.5))*(1+gammp(1.5,delta))
285        endif
286
287        fSubS = 0.5*(1.0+erf( (r0-BS)/sqrt(2.0*v_d) ) )
288        if (fSubS <= 0.0)
289                fSubS = 1.e-10
290        endif
291//      fr = 1.0 + sqrt(v_d)*exp(-1.0*delta) /(r0*fSubS*sqrt(2.0*Pi))
292//      fv = inc_gamma/(fSubS*sqrt(Pi)) - r0^2*(fr-1.0)^2/v_d
293//
294//      rmd = fr*r0
295//      v_r1 = v_b + fv*v_d +v_g
296//
297//      rm = rmd + 0.5*v_r1/rmd
298//      v_r = v_r1 - 0.5*(v_r1/rmd)^2
299//      if (v_r < 0.0)
300//              v_r = 0.0
301//      endif
302
303        Variable kap,a_val,a_val_L2,proj_DDet
304       
305        kap = 2*pi/lambda
306        a_val = L2*(L1+L2)*g/2*(m_h)^2
307        a_val_L2 = a_val/L2*1e-16               //convert 1/cm^2 to 1/A^2
308
309
310        // the detector pixel is square, so correct for phi
311        proj_DDet = DDet*cos(phi) + DDet*sin(phi)
312
313
314///////// OLD - don't use ---
315//in terms of Q_parallel ("x") and Q_perp ("y") - this works, since parallel is in the direction of Q and I
316// can calculate that from the QxQy (I just need the projection)
317//// for test case with no gravity, set a_val = 0
318//// note that gravity has no wavelength dependence. the lambda^4 cancels out.
319////
320////    a_val = 0
321////    a_val_l2 = 0
322//
323//     
324//      // this is really sigma_Q_parallel
325//      SigmaQX = kap*kap/12 * (3*(S1/L1)^2 + 3*(S2/LP)^2 + (proj_DDet/L2)^2 + (sin(phi))^2*8*(a_val_L2)^2*lambda^4*lambdaWidth^2)
326//      SigmaQX += inQ*inQ*v_lambda
327//
328//      //this is really sigma_Q_perpendicular
329//      proj_DDet = DDet*sin(phi) + DDet*cos(phi)               //not necessary, since DDet is the same in both X and Y directions
330//
331//      SigmaQY = kap*kap/12 * (3*(S1/L1)^2 + 3*(S2/LP)^2 + (proj_DDet/L2)^2 + (cos(phi))^2*8*(a_val_L2)^2*lambda^4*lambdaWidth^2)
332//     
333//      SigmaQX = sqrt(SigmaQX)
334//      SigmaQy = sqrt(SigmaQY)
335//     
336
337/////////////////////////////////////////////////
338/////   
339//      ////// this is all new, inclusion of gravity effect into the parallel component
340//       perpendicular component is purely geometric, no gravity component
341//
342// the shadow factor is calculated as above -so keep the above calculations, even though
343// most of them are redundant.
344//
345       
346////    //
347        Variable yg_d,acc,sdd,ssd,lambda0,DL_L,sig_l
348        Variable var_qlx,var_qly,var_ql,qx,qy,sig_perp,sig_para, sig_para_new
349       
350        G = 981.  //!   ACCELERATION OF GRAVITY, CM/SEC^2
351        acc = vz_1              //      3.956E5 //!     CONVERT WAVELENGTH TO VELOCITY CM/SEC
352        SDD = L2                //1317
353        SSD = L1                //1627          //cm
354        lambda0 = lambda                //              15
355        DL_L = lambdaWidth              //0.236
356        SIG_L = DL_L/sqrt(6)
357        YG_d = -0.5*G*SDD*(SSD+SDD)*(LAMBDA0/acc)^2
358/////   Print "DISTANCE BEAM FALLS DUE TO GRAVITY (CM) = ",YG
359//              Print "Gravity q* = ",-2*pi/lambda0*2*yg_d/sdd
360       
361        sig_perp = kap*kap/12 * (3*(S1/L1)^2 + 3*(S2/LP)^2 + (proj_DDet/L2)^2)
362        sig_perp = sqrt(sig_perp)
363       
364       
365        FindQxQy(inQ,phi,qx,qy)
366
367// missing a factor of 2 here, and the form is different than the paper, so re-write   
368//      VAR_QLY = SIG_L^2 * (QY+4*PI*YG_d/(2*SDD*LAMBDA0))^2
369//      VAR_QLX = (SIG_L*QX)^2
370//      VAR_QL = VAR_QLY + VAR_QLX  //! WAVELENGTH CONTRIBUTION TO VARIANCE
371//      sig_para = (sig_perp^2 + VAR_QL)^0.5
372       
373        // r_dist is passed in, [=]cm
374        // from the paper
375        a_val = 0.5*G*SDD*(SSD+SDD)*m_h^2 * 1e-16               //units now are cm /(A^2)
376       
377        var_QL = 1/6*(kap/SDD)^2*(DL_L)^2*(r_dist^2 - 4*r_dist*a_val*lambda0^2*sin(phi) + 4*a_val^2*lambda0^4)
378        sig_para_new = (sig_perp^2 + VAR_QL)^0.5
379       
380       
381///// return values PBR
382        SigmaQX = sig_para_new
383        SigmaQy = sig_perp
384       
385////   
386       
387        results = "success"
388        Return results
389End
390
391
392
393
394//Utility function that returns the detector resolution (in cm)
395//Global values are set in the Initialize procedure
396//
397//
398// - called by CircSectAvg.ipf, RectAnnulAvg.ipf, and ProtocolAsPanel.ipf
399//
400// fileStr is passed as TextRead[3]
401// detStr is passed as TextRead[9]
402//
403// *** as of Jan 2008, depricated. Now detector pixel sizes are read from the file header
404// rw[10] = x size (mm); rw[13] = y size (mm)
405//
406Function xDetectorPixelResolution(fileStr,detStr)
407        String fileStr,detStr
408       
409        Variable DDet
410        String instr=fileStr[1,3]       //filestr is "[NGnSANSn] " or "[NGnSANSnn]" (11 characters total)
411       
412        NVAR PixelResNG3_ILL = root:myGlobals:PixelResNG3_ILL           //pixel resolution in cm
413        NVAR PixelResNG5_ILL = root:myGlobals:PixelResNG5_ILL
414        NVAR PixelResNG7_ILL = root:myGlobals:PixelResNG7_ILL
415        NVAR PixelResNGA_ILL = root:myGlobals:PixelResNGA_ILL
416        NVAR PixelResNG3_ORNL = root:myGlobals:PixelResNG3_ORNL
417        NVAR PixelResNG5_ORNL = root:myGlobals:PixelResNG5_ORNL
418        NVAR PixelResNG7_ORNL = root:myGlobals:PixelResNG7_ORNL
419        NVAR PixelResNGA_ORNL = root:myGlobals:PixelResNGA_ORNL
420        NVAR PixelResDefault = root:myGlobals:PixelResDefault
421       
422        strswitch(instr)
423                case "NG3":
424                        if(cmpstr(detStr, "ILL   ") == 0 )
425                                DDet= PixelResNG3_ILL
426                        else
427                                DDet = PixelResNG3_ORNL //detector is ordella-type
428                        endif
429                        break
430                case "NG5":
431                        if(cmpstr(detStr, "ILL   ") == 0 )
432                                DDet= PixelResNG5_ILL
433                        else
434                                DDet = PixelResNG5_ORNL //detector is ordella-type
435                        endif
436                        break
437                case "NG7":
438                        if(cmpstr(detStr, "ILL   ") == 0 )
439                                DDet= PixelResNG7_ILL
440                        else
441                                DDet = PixelResNG7_ORNL //detector is ordella-type
442                        endif
443                        break
444                case "NGA":
445                        if(cmpstr(detStr, "ILL   ") == 0 )
446                                DDet= PixelResNGA_ILL
447                        else
448                                DDet = PixelResNGA_ORNL //detector is ordella-type
449                        endif
450                        break
451                default:                                                       
452                        //return error?
453                        DoAlert 0, "No matching instrument xDetectorPixelResolution-- Using default resolution"
454                        DDet = PixelResDefault  //0.5 cm, typical for new ORNL detectors
455        endswitch
456       
457        return(DDet)
458End
459
460//Utility function that returns the detector deadtime (in seconds)
461//Global values are set in the Initialize procedure
462//
463// - called by WorkFileUtils.ipf
464//
465// fileStr is passed as TextRead[3]
466// detStr is passed as TextRead[9]
467// dateAndTimeStr is passed as TextRead[1]
468//      --- if no date/time string is passed, ICE values are the default
469//
470// Due to the switch from VAX -> ICE, there were some hardware changes that led to
471// a change in the effective detector dead time. The dead time was re-measured by J. Barker
472// as follows:
473//      Instrument                              Date measured                           deadtime constant
474//      NG3                                                     DECEMBER 2009                           1.5 microseconds
475//      NG7                                                     APRIL2010                                       2.3 microseconds
476//      NGA                                                     TBD 2013
477// TODO_10m: measure proper dead time constants
478//
479//
480// The day of the switch to ICE on NG7 was 25-FEB-2010 (per J. Krzywon)
481// The day of the switch to ICE on NG3 was 23-JUL-2009 (per C. Gagnon)
482//
483// so any data after these dates is to use the new dead time constant. The switch is made on the
484// data collection date.
485//
486//
487Function DetectorDeadtime(fileStr,detStr,[dateAndTimeStr])
488        String fileStr,detStr,dateAndTimeStr
489       
490        Variable deadtime
491        String instr=fileStr[1,3]       //filestr is "[NGnSANSn] " or "[NGnSANSnn]" (11 characters total)
492       
493        NVAR DeadtimeNG3_ILL = root:myGlobals:DeadtimeNG3_ILL           //pixel resolution in cm
494        NVAR DeadtimeNG5_ILL = root:myGlobals:DeadtimeNG5_ILL
495        NVAR DeadtimeNG7_ILL = root:myGlobals:DeadtimeNG7_ILL
496        NVAR DeadtimeNGA_ILL = root:myGlobals:DeadtimeNGA_ILL
497        NVAR DeadtimeNG3_ORNL_VAX = root:myGlobals:DeadtimeNG3_ORNL_VAX
498        NVAR DeadtimeNG3_ORNL_ICE = root:myGlobals:DeadtimeNG3_ORNL_ICE
499        NVAR DeadtimeNG5_ORNL = root:myGlobals:DeadtimeNG5_ORNL
500        NVAR DeadtimeNG7_ORNL_VAX = root:myGlobals:DeadtimeNG7_ORNL_VAX
501        NVAR DeadtimeNG7_ORNL_ICE = root:myGlobals:DeadtimeNG7_ORNL_ICE
502        NVAR DeadtimeNGA_ORNL_ICE = root:myGlobals:DeadtimeNGA_ORNL_ICE
503        NVAR DeadtimeDefault = root:myGlobals:DeadtimeDefault
504       
505        // if no date string is passed, default to the ICE values
506        if(strlen(dateAndTimeStr)==0)
507                dateAndTimeStr = "01-JAN-2011"          //dummy date to force to ICE values
508        endif
509       
510       
511        Variable NG3_to_ICE = ConvertVAXDay2secs("23-JUL-2009")
512        Variable NG7_to_ICE = ConvertVAXDay2secs("25-FEB-2010")
513        Variable fileTime = ConvertVAXDay2secs(dateAndTimeStr)
514
515       
516        strswitch(instr)
517                case "NG3":
518                        if(cmpstr(detStr, "ILL   ") == 0 )
519                                deadtime= DeadtimeNG3_ILL
520                        else
521                                if(fileTime > NG3_to_ICE)
522                                        deadtime = DeadtimeNG3_ORNL_ICE //detector is ordella-type, using ICE hardware
523                                else
524                                        deadtime = DeadtimeNG3_ORNL_VAX //detector is ordella-type
525                                endif
526                        endif
527                        break
528                case "NG5":
529                        if(cmpstr(detStr, "ILL   ") == 0 )
530                                deadtime= DeadtimeNG5_ILL
531                        else
532                                deadtime = DeadtimeNG5_ORNL     //detector is ordella-type
533                        endif
534                        break
535                case "NG7":
536                        if(cmpstr(detStr, "ILL   ") == 0 )
537                                deadtime= DeadtimeNG7_ILL
538                        else
539                                if(fileTime > NG7_to_ICE)
540                                        deadtime = DeadtimeNG7_ORNL_ICE //detector is ordella-type, using ICE hardware
541                                else
542                                        deadtime = DeadtimeNG7_ORNL_VAX //detector is ordella-type
543                                endif
544                        endif
545                        break
546                case "NGA":
547                        if(cmpstr(detStr, "ILL   ") == 0 )
548                                deadtime= DeadtimeNGA_ILL
549                        else
550                                deadtime = DeadtimeNGA_ORNL_ICE //detector is ordella-type, using ICE hardware
551                        endif
552                        Print "Using fictional values for NGA dead time"
553                        break
554                default:                                                       
555                        //return error?
556                        DoAlert 0, "no matching instrument DetectorDeadtime, using default"
557                        deadtime = DeadtimeDefault      //1e-6 seconds, typical for new ORNL detectors
558        endswitch
559       
560        return(deadtime)
561End
562
563// converts ONLY DD-MON-YYYY portion of the data collection time
564// to a number of seconds from midnight on 1/1/1904, as Igor likes to do
565//
566// dateAndTime is the full string of "dd-mon-yyyy hh:mm:ss" as returned by the function
567// getFileCreationDate(file)
568//
569Function ConvertVAXDay2secs(dateAndTime)
570        string dateAndTime
571       
572        Variable day,yr,mon,time_secs
573        string monStr
574
575        sscanf dateandtime,"%d-%3s-%4d",day,monStr,yr
576        mon = monStr2num(monStr)
577//      print yr,mon,day
578        time_secs = date2secs(yr,mon,day)
579
580        return(time_secs)
581end
582
583// dd-mon-yyyy hh:mm:ss -> seconds
584// the VAX uses 24 hr time for hh
585//
586Function ConvertVAXDateTime2secs(dateAndTime)
587        string dateAndTime
588       
589        Variable day,yr,mon,hh,mm,ss,time_secs
590        string str,monStr
591       
592        str=dateandtime
593        sscanf str,"%d-%3s-%4d %d:%d:%d",day,monStr,yr,hh,mm,ss
594        mon = monStr2num(monStr)
595//      print yr,mon,day,hh,mm,ss
596        time_secs = date2secs(yr,mon,day)
597        time_secs += hh*3600 + mm*60 + ss
598
599
600        return(time_secs)
601end
602
603// takes a month string and returns the corresponding number
604//
605Function monStr2num(monStr)
606        String monStr
607       
608        String list=";JAN;FEB;MAR;APR;MAY;JUN;JUL;AUG;SEP;OCT;NOV;DEC;"
609        return(WhichListItem(monStr, list ,";"))
610end
611
612
613//make a three character string of the run number
614//Moved to facility utils
615Function/S RunDigitString(num)
616        Variable num
617       
618        String numStr=""
619        if(num<10)
620                numStr = "00"+num2str(num)
621        else
622                if(num<100)
623                        numStr = "0"+num2str(num)
624                else
625                        numStr = num2str(num)
626                Endif
627        Endif
628        //Print "numstr = ",numstr
629        return(numstr)
630End
631
632//given a filename of a SANS data filename of the form
633//TTTTTnnn.SAn_TTT_Txxx
634//returns the prefix "TTTTT" as some number of characters
635//returns "" as an invalid file prefix
636//
637// NCNR-specifc, does not really belong here - but it's a beta procedure used for the
638// Combine Files Panel
639//
640Function/S GetPrefixStrFromFile(item)
641        String item
642        String invalid = ""     //"" is not a valid run prefix, since it's text
643        Variable num=-1
644       
645        //find the "dot"
646        String runStr=""
647        Variable pos = strsearch(item,".",0)
648        if(pos == -1)
649                //"dot" not found
650                return (invalid)
651        else
652                //found, skip the three characters preceeding it
653                if (pos <=3)
654                        //not enough characters
655                        return (invalid)
656                else
657                        runStr = item[0,pos-4]
658                        return (runStr)
659                Endif
660        Endif
661End
662
663
664
665
666/////VAX filename/Run number parsing utilities
667//
668// a collection of uilities for processing vax filenames
669//and processing lists (especially for display in popup menus)
670//
671//required to correctly account for VAX supplied version numbers, which
672//may or may not be removed by the ftp utility
673//
674// - parses lists of run numbers into real filenames
675// - selects proper detector constants
676//
677//**************************
678//
679//given a filename of a SANS data filename of the form
680//TTTTTnnn.SAn_TTT_Txxx
681//returns the run number "nnn" as a number
682//returns -1 as an invalid file number
683//
684// called by several ipfs
685//
686//
687Function GetRunNumFromFile(item)
688        String item
689        Variable invalid = -1   //negative numbers are invalid
690        Variable num=-1
691       
692        //find the "dot"
693        String runStr=""
694        Variable pos = strsearch(item,".",0)
695        if(pos == -1)
696                //"dot" not found
697                return (invalid)
698        else
699                //found, get the three characters preceeding it
700                if (pos <=2)
701                        //not enough characters
702                        return (invalid)
703                else
704                        runStr = item[pos-3,pos-1]
705                        //convert to a number
706                        num = str2num(runStr)
707                        //if valid, return it
708                        if (num == NaN)
709                                //3 characters were not a number
710                                return (invalid)
711                        else
712                                //run was OK
713                                return (num)
714                        Endif
715                Endif
716        Endif
717End
718
719//given a filename of a SANS data filename of the form
720//TTTTTnnn.SAn_TTT_Txxx
721//returns the run number "nnn" as a STRING of THREE characters
722//returns "ABC" as an invalid file number
723//
724// local function to aid in locating files by run number
725//
726Function/S GetRunNumStrFromFile(item)
727        String item
728        String invalid = "ABC"  //"ABC" is not a valid run number, since it's text
729        Variable num=-1
730       
731        //find the "dot"
732        String runStr=""
733        Variable pos = strsearch(item,".",0)
734        if(pos == -1)
735                //"dot" not found
736                return (invalid)
737        else
738                //found, get the three characters preceeding it
739                if (pos <=2)
740                        //not enough characters
741                        return (invalid)
742                else
743                        runStr = item[pos-3,pos-1]
744                        return (runStr)
745                Endif
746        Endif
747End
748
749//returns a string containing the full path to the file containing the
750//run number "num". The null string is returned if no valid file can be found
751//the path "catPathName" used and is hard-wired, will abort if this path does not exist
752//the file returned will be a RAW SANS data file, other types of files are
753//filtered out.
754//
755// called by Buttons.ipf and Transmission.ipf, and locally by parsing routines
756//
757Function/S FindFileFromRunNumber(num)
758        Variable num
759       
760        String fullName="",partialName="",item=""
761        //get list of raw data files in folder that match "num" (add leading zeros)
762        if( (num>999) || (num<=0) )
763                //Print "error in  FindFileFromRunNumber(num), file number too large or too small"
764                Return ("")
765        Endif
766        //make a three character string of the run number
767        String numStr=""
768        if(num<10)
769                numStr = "00"+num2str(num)
770        else
771                if(num<100)
772                        numStr = "0"+num2str(num)
773                else
774                        numStr = num2str(num)
775                Endif
776        Endif
777        //Print "numstr = ",numstr
778       
779        //make sure that path exists
780        PathInfo catPathName
781        String path = S_path
782        if (V_flag == 0)
783                Abort "folder path does not exist - use Pick Path button"
784        Endif
785        String list="",newList="",testStr=""
786       
787        list = IndexedFile(catPathName,-1,"????")       //get all files in folder
788        //find (the) one with the number in the run # location in the name
789        Variable numItems,ii,runFound,isRAW
790        numItems = ItemsInList(list,";")                //get the new number of items in the list
791        ii=0
792        do
793                //parse through the list in this order:
794                // 1 - does item contain run number (as a string) "TTTTTnnn.SAn_XXX_Tyyy"
795                // 2 - exclude by isRaw? (to minimize disk access)
796                item = StringFromList(ii, list  ,";" )
797                if(strlen(item) != 0)
798                        //find the run number, if it exists as a three character string
799                        testStr = GetRunNumStrFromFile(item)
800                        runFound= cmpstr(numStr,testStr)        //compare the three character strings, 0 if equal
801                        if(runFound == 0)
802                                //the run Number was found
803                                //build valid filename
804                                partialName = FindValidFileName(item)
805                                if(strlen(partialName) != 0)            //non-null return from FindValidFileName()
806                                        fullName = path + partialName
807                                        //check if RAW, if so,this must be the file!
808                                        isRAW = CheckIfRawData(fullName)
809                                        if(isRaw)
810                                                //stop here
811                                                return(fullname)
812                                        Endif
813                                Endif
814                        Endif
815                Endif
816                ii+=1
817        while(ii<numItems)              //process all items in list
818        Return ("")     //null return if file not found in list
819End
820
821//function to test a binary file to see if it is a RAW binary SANS file
822//first checks the total bytes in the file (which for raw data is 33316 bytes)
823//**note that the "DIV" file will also show up as a raw file by the run field
824//should be listed in CAT/SHORT and in patch windows
825//
826//Function then checks the file fname (full path:file) for "RAW" run.type field
827//if not found, the data is not raw data and zero is returned
828//
829// called by many procedures (both external and local)
830//
831Function CheckIfRawData(fname)
832        String fname
833       
834        Variable refnum,totalBytes
835        String testStr=""
836       
837        Open/R/T="????TEXT" refNum as fname
838        if(strlen(s_filename) == 0)     //user cancel (/Z not used, so V_flag not set)
839                return(0)
840        endif
841       
842        //get the total number of bytes in the file
843        FStatus refNum
844        totalBytes = V_logEOF
845        //Print totalBytes
846        if(totalBytes < 100)
847                Close refNum
848                return(0)               //not a raw file
849        endif
850        FSetPos refNum,75
851        FReadLine/N=3 refNum,testStr
852        Close refNum
853       
854        if(totalBytes == 33316 && ( cmpstr(testStr,"RAW")==0 ||  cmpstr(testStr,"SIM")==0))
855                //true, is raw data file
856                Return(1)
857        else
858                //some other file
859                Return(0)
860        Endif
861End
862
863//function to test a file to see if it is a DIV file
864//
865// returns truth 0/1
866//
867// called by many procedures (both external and local)
868//
869Function CheckIfDIVData(fname)
870        String fname
871       
872
873        Variable refnum,totalBytes
874//      String testStr=""
875       
876        Open/R/T="????TEXT" refNum as fname
877        if(strlen(s_filename) == 0)     //user cancel (/Z not used, so V_flag not set)
878                return(0)
879        endif
880       
881        //get the total number of bytes in the file
882        FStatus refNum
883        totalBytes = V_logEOF
884        //Print totalBytes
885        if(totalBytes < 100)
886                Close refNum
887                return(0)               //not a raw file
888        endif
889//      FSetPos refNum,75
890//      FReadLine/N=3 refNum,testStr
891        Close refNum
892       
893        if(totalBytes == 66116)         // && ( cmpstr(testStr,"RAW")==0 ||  cmpstr(testStr,"SIM")==0))
894                //true, is raw data file
895                Return(1)
896        else
897                //some other file
898                Return(0)
899        Endif
900
901End
902
903//function to check the header of a raw data file (full path specified by fname)
904//checks the field of the x-position of the beamstop during data collection
905//if the x-position is more negative (farther to the left) than xTol(input)
906//the the beamstop is "out" and the file is a transmission run and not a scattering run
907//xtol typically set at -5 (cm) - trans runs have bs(x) at -10 to -15 cm
908// function returns 1 if beamstop is out, 0 if beamstop is in
909//
910// tolerance is set as a global value "root:myGlobals:BeamstopXTol"
911//
912// called by Transmission.ipf, CatVSTable.ipf, NSORT.ipf
913//
914Function isTransFile(fName)
915        String fname
916       
917        Variable refnum,xpos
918        NVAR xTol = root:myGlobals:BeamstopXTol
919       
920        //pos = 369, read one real value
921       
922        SetDataFolder root:
923        String GBLoadStr="GBLoadWave/O/N=tempGBwave/T={2,2}/J=2/W=1/Q"
924        String strToExecute=""
925        // 1 R*4 value
926        strToExecute = GBLoadStr + "/S=368/U=1" + "\"" + fname + "\""
927        Execute strToExecute
928        Wave w=$"root:tempGBWave0"
929        xPos = w[0]
930        KillWaves/Z w
931        //Print "xPos = ",xpos
932       
933        if(xpos<=xTol)
934                //xpos is farther left (more negative) than xtol (currently -5 cm)
935                Return(1)
936        else
937                //some other file
938                Return(0)
939        Endif
940End
941
942
943//function to remove all spaces from names when searching for filenames
944//the filename (as saved) will never have interior spaces (TTTTTnnn_AB _Bnnn)
945//but the text field in the header WILL, if less than 3 characters were used for the
946//user's initials, and can have leading spaces if prefix was less than 5 characters
947//
948//returns a string identical to the original string, except with the interior spaces removed
949//
950// local function for file name manipulation
951//
952Function/S RemoveAllSpaces(str)
953        String str
954       
955        String tempstr = str
956        Variable ii,spc,len             //should never be more than 2 or 3 trailing spaces in a filename
957        ii=0
958        do
959                len = strlen(tempStr)
960                spc = strsearch(tempStr," ",0)          //is the last character a space?
961                if (spc == -1)
962                        break           //no more spaces found, get out
963                endif
964                str = tempstr
965                tempStr = str[0,(spc-1)] + str[(spc+1),(len-1)] //remove the space from the string
966        While(1)        //should never be more than 2 or 3
967       
968        If(strlen(tempStr) < 1)
969                tempStr = ""            //be sure to return a null string if problem found
970        Endif
971       
972        //Print strlen(tempstr)
973       
974        Return(tempStr)
975               
976End
977
978
979//Function attempts to find valid filename from partial name by checking for
980// the existence of the file on disk.
981// - checks as is
982// - adds ";vers" for possible VAX files
983// - strips spaces
984// - permutations of upper/lowercase
985//
986// added 11/99 - uppercase and lowercase versions of the file are tried, if necessary
987// since from marquee, the filename field (textread[0]) must be used, and can be a mix of
988// upper/lowercase letters, while the filename on the server (should) be all caps
989// now makes repeated calls to ValidFileString()
990//
991// returns a valid filename (No path prepended) or a null string
992//
993// called by any functions, both external and local
994//
995Function/S FindValidFilename(partialName)
996        String PartialName
997       
998        String retStr=""
999       
1000        //try name with no changes - to allow for ABS files that have spaces in the names 12APR04
1001        retStr = ValidFileString(partialName)
1002        if(cmpstr(retStr,"") !=0)
1003                //non-null return
1004                return(retStr)
1005        Endif
1006       
1007        //if the partial name is derived from the file header, there can be spaces at the beginning
1008        //or in the middle of the filename - depending on the prefix and initials used
1009        //
1010        //remove any leading spaces from the name before starting
1011        partialName = RemoveAllSpaces(partialName)
1012       
1013        //try name with no spaces
1014        retStr = ValidFileString(partialName)
1015        if(cmpstr(retStr,"") !=0)
1016                //non-null return
1017                return(retStr)
1018        Endif
1019       
1020        //try all UPPERCASE
1021        partialName = UpperStr(partialName)
1022        retStr = ValidFileString(partialName)
1023        if(cmpstr(retStr,"") !=0)
1024                //non-null return
1025                return(retStr)
1026        Endif
1027       
1028        //try all lowercase (ret null if failure)
1029        partialName = LowerStr(partialName)
1030        retStr = ValidFileString(partialName)
1031        if(cmpstr(retStr,"") !=0)
1032                //non-null return
1033                return(retStr)
1034        else
1035                return(retStr)
1036        Endif
1037End
1038
1039// Function checks for the existence of a file
1040// partialName;vers (to account for VAX filenaming conventions)
1041// The partial name is tried first with no version number
1042//
1043// *** the PATH is hard-wired to catPathName (which is assumed to exist)
1044// version numers up to ;10 are tried
1045// only the "name;vers" is returned if successful. The path is not prepended
1046//
1047// local function
1048//
1049Function/S ValidFileString(partialName)
1050        String partialName
1051       
1052        String tempName = "",msg=""
1053        Variable ii,refnum
1054       
1055        ii=0
1056        do
1057                if(ii==0)
1058                        //first pass, try the partialName
1059                        tempName = partialName
1060                        Open/Z/R/T="????TEXT"/P=catPathName refnum tempName     //Does open file (/Z flag)
1061                        if(V_flag == 0)
1062                                //file exists
1063                                Close refnum            //YES needed,
1064                                break
1065                        endif
1066                else
1067                        tempName = partialName + ";" + num2str(ii)
1068                        Open/Z/R/T="????TEXT"/P=catPathName refnum tempName
1069                        if(V_flag == 0)
1070                                //file exists
1071                                Close refnum
1072                                break
1073                        endif
1074                Endif
1075                ii+=1
1076                //print "ii=",ii
1077        while(ii<11)
1078        //go get the selected bits of information, using tempName, which exists
1079        if(ii>=11)
1080                //msg = partialName + " not found. is version number > 11?"
1081                //DoAlert 0, msg
1082                //PathInfo catPathName
1083                //Print S_Path
1084                Return ("")             //use null string as error condition
1085        Endif
1086       
1087        Return (tempName)
1088End
1089
1090//returns a string containing filename (WITHOUT the ;vers)
1091//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
1092//with the folders separated by colons
1093//
1094// called by MaskUtils.ipf, ProtocolAsPanel.ipf, WriteQIS.ipf
1095//
1096Function/S GetFileNameFromPathNoSemi(fullPath)
1097        String fullPath
1098       
1099        Variable offset1,offset2
1100        String filename=""
1101        //String PartialPath
1102        offset1 = 0
1103        do
1104                offset2 = StrSearch(fullPath, ":", offset1)
1105                if (offset2 == -1)                              // no more colons ?
1106                        fileName = FullPath[offset1,strlen(FullPath) ]
1107                        //PartialPath = FullPath[0, offset1-1]
1108                        break
1109                endif
1110                offset1 = offset2+1
1111        while (1)
1112       
1113        //remove version number from name, if it's there - format should be: filename;N
1114        filename =  StringFromList(0,filename,";")              //returns null if error
1115       
1116        Return filename
1117End
1118
1119//returns a string containing filename (INCLUDING the ;vers)
1120//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
1121//with the folders separated by colons
1122//
1123// local, currently unused
1124//
1125Function/S GetFileNameFromPathKeepSemi(fullPath)
1126        String fullPath
1127       
1128        Variable offset1,offset2
1129        String filename
1130        //String PartialPath
1131        offset1 = 0
1132        do
1133                offset2 = StrSearch(fullPath, ":", offset1)
1134                if (offset2 == -1)                              // no more colons ?
1135                        fileName = FullPath[offset1,strlen(FullPath) ]
1136                        //PartialPath = FullPath[0, offset1-1]
1137                        break
1138                endif
1139                offset1 = offset2+1
1140        while (1)
1141       
1142        //keep version number from name, if it's there - format should be: filename;N
1143       
1144        Return filename
1145End
1146
1147//given the full path and filename (fullPath), strips the data path
1148//(Mac-style, separated by colons) and returns this path
1149//this partial path is the same string that would be returned from PathInfo, for example
1150//
1151// - allows the user to save to a different path than catPathName
1152//
1153// called by WriteQIS.ipf
1154//
1155Function/S GetPathStrFromfullName(fullPath)
1156        String fullPath
1157       
1158        Variable offset1,offset2
1159        //String filename
1160        String PartialPath
1161        offset1 = 0
1162        do
1163                offset2 = StrSearch(fullPath, ":", offset1)
1164                if (offset2 == -1)                              // no more colons ?
1165                        //fileName = FullPath[offset1,strlen(FullPath) ]
1166                        PartialPath = FullPath[0, offset1-1]
1167                        break
1168                endif
1169                offset1 = offset2+1
1170        while (1)
1171       
1172        Return PartialPath
1173End
1174
1175//given the VAX filename, pull off the first 8 characters to make a valid
1176//file string that can be used for naming averaged 1-d files
1177//
1178// called by ProtocolAsPanel.ipf and Tile_2D.ipf
1179//
1180Function/S GetNameFromHeader(fullName)
1181        String fullName
1182        String temp, newName = ""
1183        Variable spc,ii=0
1184       
1185        //filename is 20 characters NNNNNxxx.SAn_NNN_NNN
1186        //want the first 8 characters, NNNNNxxx, then strip off any spaces at the beginning
1187        //NNNNN was entered as less than 5 characters
1188        //returns a null string if no name can be found
1189        do
1190                temp = fullname[ii,7]           //characters ii,7 of the name
1191                spc = strsearch(temp," ",0)
1192                if (spc == -1)
1193                        break           //no more spaces found
1194                endif
1195                ii+=1
1196        While(ii<8)
1197       
1198        If(strlen(temp) < 1)
1199                newName = ""            //be sure to return a null string if problem found
1200        else
1201                newName = temp
1202        Endif
1203       
1204        Return(newName)
1205End
1206
1207//list (input) is a list, typically returned from IndexedFile()
1208//which is semicolon-delimited, and may contain filenames from the VAX
1209//that contain version numbers, where the version number appears as a separate list item
1210//(and also as a non-existent file)
1211//these numbers must be purged from the list, especially for display in a popup
1212//or list processing of filenames
1213//the function returns the list, cleaned of version numbers (up to 11)
1214//raw data files will typically never have a version number other than 1.
1215//
1216// if there are no version numbers in the list, the input list is returned
1217//
1218// called by CatVSTable.ipf, NSORT.ipf, Transmission.ipf, WorkFileUtils.ipf
1219//
1220Function/S RemoveVersNumsFromList(list)
1221        String list
1222       
1223        //get rid of version numbers first (up to 11)
1224        Variable ii,num
1225        String item
1226        num = ItemsInList(list,";")
1227        ii=1
1228        do
1229                item = num2str(ii)
1230                list = RemoveFromList(item, list ,";" )
1231                ii+=1
1232        while(ii<12)
1233       
1234        return (list)
1235End
1236
1237//input is a list of run numbers, and output is a list of filenames (not the full path)
1238//*** input list must be COMMA delimited***
1239//output is equivalent to selecting from the CAT table
1240//if some or all of the list items are valid filenames, keep them...
1241//if an error is encountered, notify of the offending element and return a null list
1242//
1243//output is COMMA delimited
1244//
1245// this routine is expecting that the "ask", "none" special cases are handled elsewhere
1246//and not passed here
1247//
1248// called by Marquee.ipf, MultipleReduce.ipf, ProtocolAsPanel.ipf
1249//
1250Function/S ParseRunNumberList(list)
1251        String list
1252       
1253        String newList="",item="",tempStr=""
1254        Variable num,ii,runNum
1255       
1256        //expand number ranges, if any
1257        list = ExpandNumRanges(list)
1258       
1259        num=itemsinlist(list,",")
1260       
1261        for(ii=0;ii<num;ii+=1)
1262                //get the item
1263                item = StringFromList(ii,list,",")
1264                //is it already a valid filename?
1265                tempStr=FindValidFilename(item) //returns filename if good, null if error
1266                if(strlen(tempstr)!=0)
1267                        //valid name, add to list
1268                        //Print "it's a file"
1269                        newList += tempStr + ","
1270                else
1271                        //not a valid name
1272                        //is it a number?
1273                        runNum=str2num(item)
1274                        //print runnum
1275                        if(numtype(runNum) != 0)
1276                                //not a number -  maybe an error                       
1277                                DoAlert 0,"List item "+item+" is not a valid run number or filename. Please enter a valid number or filename."
1278                                return("")
1279                        else
1280                                //a run number or an error
1281                                tempStr = GetFileNameFromPathNoSemi( FindFileFromRunNumber(runNum) )
1282                                if(strlen(tempstr)==0)
1283                                        //file not found, error
1284                                        DoAlert 0,"List item "+item+" is not a valid run number. Please enter a valid number."
1285                                        return("")
1286                                else
1287                                        newList += tempStr + ","
1288                                endif
1289                        endif
1290                endif
1291        endfor          //loop over all items in list
1292       
1293        return(newList)
1294End
1295
1296//takes a comma delimited list that MAY contain number range, and
1297//expands any range of run numbers into a comma-delimited list...
1298//and returns the new list - if not a range, return unchanged
1299//
1300// local function
1301//
1302Function/S ExpandNumRanges(list)
1303        String list
1304       
1305        String newList="",dash="-",item,str
1306        Variable num,ii,hasDash
1307       
1308        num=itemsinlist(list,",")
1309//      print num
1310        for(ii=0;ii<num;ii+=1)
1311                //get the item
1312                item = StringFromList(ii,list,",")
1313                //does it contain a dash?
1314                hasDash = strsearch(item,dash,0)                //-1 if no dash found
1315                if(hasDash == -1)
1316                        //not a range, keep it in the list
1317                        newList += item + ","
1318                else
1319                        //has a dash (so it's a range), expand (or add null)
1320                        newList += ListFromDash(item)           
1321                endif
1322        endfor
1323       
1324        return newList
1325End
1326
1327//be sure to add a trailing comma to the return string...
1328//
1329// local function
1330//
1331Function/S ListFromDash(item)
1332        String item
1333       
1334        String numList="",loStr="",hiStr=""
1335        Variable lo,hi,ii
1336       
1337        loStr=StringFromList(0,item,"-")        //treat the range as a list
1338        hiStr=StringFromList(1,item,"-")
1339        lo=str2num(loStr)
1340        hi=str2num(hiStr)
1341        if( (numtype(lo) != 0) || (numtype(hi) !=0 ) || (lo > hi) )
1342                numList=""
1343                return numList
1344        endif
1345        for(ii=lo;ii<=hi;ii+=1)
1346                numList += num2str(ii) + ","
1347        endfor
1348       
1349        Return numList
1350End
1351
1352
1353////////Transmission
1354//******************
1355//lookup tables for attenuator transmissions
1356//NG3 and NG7 attenuators are physically different, so the transmissions are slightly different
1357//NG1 - (8m SANS) is not supported
1358//
1359// new calibration done June 2007, John Barker
1360//
1361Proc MakeNG3AttenTable()
1362
1363        NewDataFolder/O root:myGlobals:Attenuators
1364        //do explicitly to avoid data folder problems, redundant, but it must work without fail
1365        Variable num=10         //10 needed for tables after June 2007
1366
1367        Make/O/N=(num) root:myGlobals:Attenuators:ng3att0
1368        Make/O/N=(num) root:myGlobals:Attenuators:ng3att1
1369        Make/O/N=(num) root:myGlobals:Attenuators:ng3att2
1370        Make/O/N=(num) root:myGlobals:Attenuators:ng3att3
1371        Make/O/N=(num) root:myGlobals:Attenuators:ng3att4
1372        Make/O/N=(num) root:myGlobals:Attenuators:ng3att5
1373        Make/O/N=(num) root:myGlobals:Attenuators:ng3att6
1374        Make/O/N=(num) root:myGlobals:Attenuators:ng3att7
1375        Make/O/N=(num) root:myGlobals:Attenuators:ng3att8
1376        Make/O/N=(num) root:myGlobals:Attenuators:ng3att9
1377        Make/O/N=(num) root:myGlobals:Attenuators:ng3att10
1378       
1379        // and a wave for the errors at each attenuation factor
1380        Make/O/N=(num) root:myGlobals:Attenuators:ng3att0_err
1381        Make/O/N=(num) root:myGlobals:Attenuators:ng3att1_err
1382        Make/O/N=(num) root:myGlobals:Attenuators:ng3att2_err
1383        Make/O/N=(num) root:myGlobals:Attenuators:ng3att3_err
1384        Make/O/N=(num) root:myGlobals:Attenuators:ng3att4_err
1385        Make/O/N=(num) root:myGlobals:Attenuators:ng3att5_err
1386        Make/O/N=(num) root:myGlobals:Attenuators:ng3att6_err
1387        Make/O/N=(num) root:myGlobals:Attenuators:ng3att7_err
1388        Make/O/N=(num) root:myGlobals:Attenuators:ng3att8_err
1389        Make/O/N=(num) root:myGlobals:Attenuators:ng3att9_err
1390        Make/O/N=(num) root:myGlobals:Attenuators:ng3att10_err
1391       
1392       
1393        //each wave has 10 elements, the transmission of att# at the wavelengths
1394        //lambda = 4,5,6,7,8,10,12,14,17,20 (4 A and 20 A are extrapolated values)
1395        Make/O/N=(num) root:myGlobals:Attenuators:ng3lambda={4,5,6,7,8,10,12,14,17,20}
1396       
1397        // new calibration done June 2007, John Barker
1398        root:myGlobals:Attenuators:ng3att0 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
1399        root:myGlobals:Attenuators:ng3att1 = {0.444784,0.419,0.3935,0.3682,0.3492,0.3132,0.2936,0.2767,0.2477,0.22404}
1400        root:myGlobals:Attenuators:ng3att2 = {0.207506,0.1848,0.1629,0.1447,0.1292,0.1056,0.09263,0.08171,0.06656,0.0546552}
1401        root:myGlobals:Attenuators:ng3att3 = {0.092412,0.07746,0.06422,0.05379,0.04512,0.03321,0.02707,0.02237,0.01643,0.0121969}
1402        root:myGlobals:Attenuators:ng3att4 = {0.0417722,0.03302,0.02567,0.02036,0.01604,0.01067,0.00812,0.006316,0.00419,0.00282411}
1403        root:myGlobals:Attenuators:ng3att5 = {0.0187129,0.01397,0.01017,0.007591,0.005668,0.003377,0.002423,0.001771,0.001064,0.000651257}
1404        root:myGlobals:Attenuators:ng3att6 = {0.00851048,0.005984,0.004104,0.002888,0.002029,0.001098,0.0007419,0.0005141,0.000272833,0.000150624}
1405        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}
1406        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}
1407        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}
1408        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}
1409 
1410  // percent errors as measured, May 2007 values
1411  // zero error for zero attenuators, appropriate average values put in for unknown values
1412        root:myGlobals:Attenuators:ng3att0_err = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
1413        root:myGlobals:Attenuators:ng3att1_err = {0.15,0.142,0.154,0.183,0.221,0.328,0.136,0.13,0.163,0.15}
1414        root:myGlobals:Attenuators:ng3att2_err = {0.25,0.257,0.285,0.223,0.271,0.405,0.212,0.223,0.227,0.25}
1415        root:myGlobals:Attenuators:ng3att3_err = {0.3,0.295,0.329,0.263,0.323,0.495,0.307,0.28,0.277,0.3}
1416        root:myGlobals:Attenuators:ng3att4_err = {0.35,0.331,0.374,0.303,0.379,0.598,0.367,0.322,0.33,0.35}
1417        root:myGlobals:Attenuators:ng3att5_err = {0.4,0.365,0.418,0.355,0.454,0.745,0.411,0.367,0.485,0.4}
1418        root:myGlobals:Attenuators:ng3att6_err = {0.45,0.406,0.473,0.385,0.498,0.838,0.454,0.49,0.5,0.5}
1419        root:myGlobals:Attenuators:ng3att7_err = {0.6,0.554,0.692,0.425,0.562,0.991,0.715,0.8,0.8,0.8}
1420        root:myGlobals:Attenuators:ng3att8_err = {0.7,0.705,0.927,0.503,0.691,1.27,1,1,1,1}
1421        root:myGlobals:Attenuators:ng3att9_err = {1,0.862,1.172,0.799,1.104,1.891,1.5,1.5,1.5,1.5}
1422        root:myGlobals:Attenuators:ng3att10_err = {1.5,1.054,1.435,1.354,1.742,2,2,2,2,2}
1423 
1424 
1425  //old tables, pre-June 2007
1426//      Make/O/N=9 root:myGlobals:Attenuators:ng3lambda={5,6,7,8,10,12,14,17,20}
1427//      root:myGlobals:Attenuators:ng3att0 = {1, 1, 1, 1, 1, 1, 1, 1,1 }
1428//      root:myGlobals:Attenuators:ng3att1 = {0.421, 0.394, 0.371, 0.349, 0.316, 0.293, 0.274, 0.245,0.220}
1429//      root:myGlobals:Attenuators:ng3att2 = {0.187, 0.164, 0.145, 0.130, 0.106, 0.0916, 0.0808, 0.0651,0.0531}
1430//      root:myGlobals:Attenuators:ng3att3 = {0.0777, 0.0636, 0.0534, 0.0446, 0.0330, 0.0262, 0.0217, 0.0157 ,0.0116}
1431//      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}
1432//      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}
1433//      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}
1434//      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}
1435//      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}
1436//      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}
1437//      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}
1438
1439End
1440
1441// new calibration done June 2007, John Barker
1442Proc MakeNG7AttenTable()
1443
1444        NewDataFolder/O root:myGlobals:Attenuators
1445       
1446        Variable num=10         //10 needed for tables after June 2007
1447       
1448        Make/O/N=(num) root:myGlobals:Attenuators:ng7att0
1449        Make/O/N=(num) root:myGlobals:Attenuators:ng7att1
1450        Make/O/N=(num) root:myGlobals:Attenuators:ng7att2
1451        Make/O/N=(num) root:myGlobals:Attenuators:ng7att3
1452        Make/O/N=(num) root:myGlobals:Attenuators:ng7att4
1453        Make/O/N=(num) root:myGlobals:Attenuators:ng7att5
1454        Make/O/N=(num) root:myGlobals:Attenuators:ng7att6
1455        Make/O/N=(num) root:myGlobals:Attenuators:ng7att7
1456        Make/O/N=(num) root:myGlobals:Attenuators:ng7att8
1457        Make/O/N=(num) root:myGlobals:Attenuators:ng7att9
1458        Make/O/N=(num) root:myGlobals:Attenuators:ng7att10
1459       
1460        // and a wave for the errors at each attenuation factor
1461        Make/O/N=(num) root:myGlobals:Attenuators:ng7att0_err
1462        Make/O/N=(num) root:myGlobals:Attenuators:ng7att1_err
1463        Make/O/N=(num) root:myGlobals:Attenuators:ng7att2_err
1464        Make/O/N=(num) root:myGlobals:Attenuators:ng7att3_err
1465        Make/O/N=(num) root:myGlobals:Attenuators:ng7att4_err
1466        Make/O/N=(num) root:myGlobals:Attenuators:ng7att5_err
1467        Make/O/N=(num) root:myGlobals:Attenuators:ng7att6_err
1468        Make/O/N=(num) root:myGlobals:Attenuators:ng7att7_err
1469        Make/O/N=(num) root:myGlobals:Attenuators:ng7att8_err
1470        Make/O/N=(num) root:myGlobals:Attenuators:ng7att9_err
1471        Make/O/N=(num) root:myGlobals:Attenuators:ng7att10_err 
1472       
1473        //NG7 wave has 10 elements, the transmission of att# at the wavelengths
1474        //lambda =4, 5,6,7,8,10,12,14,17,20
1475        // note that some of the higher attenuations and ALL of the 4 A and 20A data is interpolated
1476        // none of these values are expected to be used in reality since the flux would be too low in practice
1477        Make/O/N=(num) root:myGlobals:Attenuators:ng7lambda={4,5,6,7,8,10,12,14,17,20}
1478
1479// New calibration, June 2007, John Barker
1480        root:myGlobals:Attenuators:ng7att0 = {1, 1, 1, 1, 1, 1, 1, 1 ,1,1}     
1481        root:myGlobals:Attenuators:ng7att1 = {0.448656,0.4192,0.3925,0.3661,0.3458,0.3098,0.2922,0.2738,0.2544,0.251352}
1482        root:myGlobals:Attenuators:ng7att2 = {0.217193,0.1898,0.1682,0.148,0.1321,0.1076,0.0957,0.08485,0.07479,0.0735965}
1483        root:myGlobals:Attenuators:ng7att3 = {0.098019,0.07877,0.06611,0.05429,0.04548,0.03318,0.02798,0.0234,0.02004,0.0202492}
1484        root:myGlobals:Attenuators:ng7att4 = {0.0426904,0.03302,0.02617,0.02026,0.0158,0.01052,0.008327,0.006665,0.005745,0.00524807}
1485        root:myGlobals:Attenuators:ng7att5 = {0.0194353,0.01398,0.01037,0.0075496,0.005542,0.003339,0.002505,0.001936,0.001765,0.00165959}
1486        root:myGlobals:Attenuators:ng7att6 = {0.00971666,0.005979,0.004136,0.002848,0.001946,0.001079,0.0007717,0.000588,0.000487337,0.000447713}
1487        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}
1488        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}
1489        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}
1490        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}
1491
1492  // percent errors as measured, May 2007 values
1493  // zero error for zero attenuators, appropriate average values put in for unknown values
1494        root:myGlobals:Attenuators:ng7att0_err = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
1495        root:myGlobals:Attenuators:ng7att1_err = {0.2,0.169,0.1932,0.253,0.298,0.4871,0.238,0.245,0.332,0.3}
1496        root:myGlobals:Attenuators:ng7att2_err = {0.3,0.305,0.3551,0.306,0.37,0.6113,0.368,0.413,0.45,0.4}
1497        root:myGlobals:Attenuators:ng7att3_err = {0.4,0.355,0.4158,0.36,0.4461,0.7643,0.532,0.514,0.535,0.5}
1498        root:myGlobals:Attenuators:ng7att4_err = {0.45,0.402,0.4767,0.415,0.5292,0.9304,0.635,0.588,0.623,0.6}
1499        root:myGlobals:Attenuators:ng7att5_err = {0.5,0.447,0.5376,0.487,0.6391,1.169,0.708,0.665,0.851,0.8}
1500        root:myGlobals:Attenuators:ng7att6_err = {0.6,0.501,0.6136,0.528,0.8796,1.708,0.782,0.874,1,1}
1501        root:myGlobals:Attenuators:ng7att7_err = {0.8,0.697,0.9149,0.583,1.173,2.427,1.242,2,2,2}
1502        root:myGlobals:Attenuators:ng7att8_err = {1,0.898,1.24,0.696,1.577,3.412,3,3,3,3}
1503        root:myGlobals:Attenuators:ng7att9_err = {1.5,1.113,1.599,1.154,2.324,4.721,5,5,5,5}
1504        root:myGlobals:Attenuators:ng7att10_err = {1.5,1.493,5,5,5,5,5,5,5,5} 
1505 
1506
1507// Pre-June 2007 calibration values - do not use these anymore 
1508////    root:myGlobals:Attenuators:ng7att0 = {1, 1, 1, 1, 1, 1, 1, 1 ,1}
1509////    root:myGlobals:Attenuators:ng7att1 = {0.418, 0.393, 0.369, 0.347, 0.313, 0.291, 0.271, 0.244, 0.219 }
1510////    root:myGlobals:Attenuators:ng7att2 = {0.189, 0.167, 0.148, 0.132, 0.109, 0.0945, 0.0830, 0.0681, 0.0560}
1511////    root:myGlobals:Attenuators:ng7att3 = {0.0784, 0.0651, 0.0541, 0.0456, 0.0340, 0.0273, 0.0223, 0.0164 , 0.0121}
1512////    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}
1513////    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}
1514////    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}
1515////    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}
1516////    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}
1517////    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}
1518////    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}
1519End
1520
1521
1522// JAN 2013 -- a duplication of the NG7 table, needs to be updated after the attenuation factors
1523// are measured
1524//
1525// TODO_10m::::
1526Proc MakeNGAAttenTable()
1527
1528        NewDataFolder/O root:myGlobals:Attenuators
1529       
1530        Variable num=10         //10 needed for tables after June 2007
1531       
1532        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt0
1533        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt1
1534        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt2
1535        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt3
1536        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt4
1537        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt5
1538        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt6
1539        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt7
1540        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt8
1541        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt9
1542        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt10
1543       
1544        // and a wave for the errors at each attenuation factor
1545        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt0_err
1546        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt1_err
1547        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt2_err
1548        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt3_err
1549        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt4_err
1550        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt5_err
1551        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt6_err
1552        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt7_err
1553        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt8_err
1554        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt9_err
1555        Make/O/N=(num) root:myGlobals:Attenuators:ngAatt10_err 
1556       
1557        //NGA wave has 10 elements, the transmission of att# at the wavelengths
1558        //lambda =4, 5,6,7,8,10,12,14,17,20
1559        // note that some of the higher attenuations and ALL of the 4 A and 20A data is interpolated
1560        // none of these values are expected to be used in reality since the flux would be too low in practice
1561        Make/O/N=(num) root:myGlobals:Attenuators:ngAlambda={4,5,6,7,8,10,12,14,17,20}
1562
1563// New calibration, June 2007, John Barker
1564        root:myGlobals:Attenuators:ngAatt0 = {1, 1, 1, 1, 1, 1, 1, 1 ,1,1}     
1565        root:myGlobals:Attenuators:ngAatt1 = {0.448656,0.4192,0.3925,0.3661,0.3458,0.3098,0.2922,0.2738,0.2544,0.251352}
1566        root:myGlobals:Attenuators:ngAatt2 = {0.217193,0.1898,0.1682,0.148,0.1321,0.1076,0.0957,0.08485,0.07479,0.0735965}
1567        root:myGlobals:Attenuators:ngAatt3 = {0.098019,0.07877,0.06611,0.05429,0.04548,0.03318,0.02798,0.0234,0.02004,0.0202492}
1568        root:myGlobals:Attenuators:ngAatt4 = {0.0426904,0.03302,0.02617,0.02026,0.0158,0.01052,0.008327,0.006665,0.005745,0.00524807}
1569        root:myGlobals:Attenuators:ngAatt5 = {0.0194353,0.01398,0.01037,0.0075496,0.005542,0.003339,0.002505,0.001936,0.001765,0.00165959}
1570        root:myGlobals:Attenuators:ngAatt6 = {0.00971666,0.005979,0.004136,0.002848,0.001946,0.001079,0.0007717,0.000588,0.000487337,0.000447713}
1571        root:myGlobals:Attenuators:ngAatt7 = {0.00207332,0.001054,0.0006462,0.0003957,0.0002368,0.0001111,7.642e-05,4.83076e-05,3.99401e-05,3.54814e-05}
1572        root:myGlobals:Attenuators:ngAatt8 = {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}
1573        root:myGlobals:Attenuators:ngAatt9 = {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}
1574        root:myGlobals:Attenuators:ngAatt10 = {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}
1575
1576  // percent errors as measured, May 2007 values
1577  // zero error for zero attenuators, appropriate average values put in for unknown values
1578        root:myGlobals:Attenuators:ngAatt0_err = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
1579        root:myGlobals:Attenuators:ngAatt1_err = {0.2,0.169,0.1932,0.253,0.298,0.4871,0.238,0.245,0.332,0.3}
1580        root:myGlobals:Attenuators:ngAatt2_err = {0.3,0.305,0.3551,0.306,0.37,0.6113,0.368,0.413,0.45,0.4}
1581        root:myGlobals:Attenuators:ngAatt3_err = {0.4,0.355,0.4158,0.36,0.4461,0.7643,0.532,0.514,0.535,0.5}
1582        root:myGlobals:Attenuators:ngAatt4_err = {0.45,0.402,0.4767,0.415,0.5292,0.9304,0.635,0.588,0.623,0.6}
1583        root:myGlobals:Attenuators:ngAatt5_err = {0.5,0.447,0.5376,0.487,0.6391,1.169,0.708,0.665,0.851,0.8}
1584        root:myGlobals:Attenuators:ngAatt6_err = {0.6,0.501,0.6136,0.528,0.8796,1.708,0.782,0.874,1,1}
1585        root:myGlobals:Attenuators:ngAatt7_err = {0.8,0.697,0.9149,0.583,1.173,2.427,1.242,2,2,2}
1586        root:myGlobals:Attenuators:ngAatt8_err = {1,0.898,1.24,0.696,1.577,3.412,3,3,3,3}
1587        root:myGlobals:Attenuators:ngAatt9_err = {1.5,1.113,1.599,1.154,2.324,4.721,5,5,5,5}
1588        root:myGlobals:Attenuators:ngAatt10_err = {1.5,1.493,5,5,5,5,5,5,5,5} 
1589 
1590End
1591
1592//returns the transmission of the attenuator (at NG3) given the attenuator number
1593//which must be an integer(to select the wave) and given the wavelength.
1594//the wavelength may be any value between 4 and 20 (A), and is interpolated
1595//between calibrated wavelengths for a given attenuator
1596//
1597// Mar 2010 - abs() added to attStr to account for ICE reporting -0.0001 as an attenuator position, which truncates to "-0"
1598Function LookupAttenNG3(lambda,attenNo,atten_err)
1599        Variable lambda, attenNo, &atten_err
1600       
1601        Variable trans
1602        String attStr="root:myGlobals:Attenuators:ng3att"+num2str(trunc(abs(attenNo)))
1603        String attErrWStr="root:myGlobals:Attenuators:ng3att"+num2str(trunc(abs(attenNo)))+"_err"
1604        String lamStr = "root:myGlobals:Attenuators:ng3lambda"
1605       
1606        if(attenNo == 0)
1607                return (1)              //no attenuation, return trans == 1
1608        endif
1609       
1610        if( (lambda < 4) || (lambda > 20 ) )
1611                Abort "Wavelength out of calibration range (4,20). You must manually enter the absolute parameters"
1612        Endif
1613       
1614        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) || !(WaveExists($attErrWStr)))
1615                Execute "MakeNG3AttenTable()"
1616        Endif
1617        //just in case creating the tables fails....
1618        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) )
1619                Abort "Attenuator lookup waves could not be found. You must manually enter the absolute parameters"
1620        Endif
1621       
1622        //lookup the value by interpolating the wavelength
1623        //the attenuator must always be an integer
1624        Wave att = $attStr
1625        Wave attErrW = $attErrWStr
1626        Wave lam = $lamstr
1627        trans = interp(lambda,lam,att)
1628        atten_err = interp(lambda,lam,attErrW)
1629
1630// the error in the tables is % error. return the standard deviation instead
1631        atten_err = trans*atten_err/100
1632               
1633//      Print "trans = ",trans
1634//      Print "trans err = ",atten_err
1635       
1636        return trans
1637End
1638
1639//returns the transmission of the attenuator (at NG7) given the attenuator number
1640//which must be an integer(to select the wave) and given the wavelength.
1641//the wavelength may be any value between 4 and 20 (A), and is interpolated
1642//between calibrated wavelengths for a given attenuator
1643//
1644// this set of tables is also used for NG5 (NG1) SANS instrument - as the attenuator has never been calibrated
1645//
1646// local function
1647//
1648// Mar 2010 - abs() added to attStr to account for ICE reporting -0.0001 as an attenuator position, which truncates to "-0"
1649Function LookupAttenNG7(lambda,attenNo,atten_err)
1650        Variable lambda, attenNo, &atten_err
1651       
1652        Variable trans
1653        String attStr="root:myGlobals:Attenuators:ng7att"+num2str(trunc(abs(attenNo)))
1654        String attErrWStr="root:myGlobals:Attenuators:ng7att"+num2str(trunc(abs(attenNo)))+"_err"
1655        String lamStr = "root:myGlobals:Attenuators:ng7lambda"
1656       
1657        if(attenNo == 0)
1658                return (1)              //no attenuation, return trans == 1
1659        endif
1660       
1661        if( (lambda < 4) || (lambda > 20 ) )
1662                Abort "Wavelength out of calibration range (4,20). You must manually enter the absolute parameters"
1663        Endif
1664       
1665        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) || !(WaveExists($attErrWStr)))
1666                Execute "MakeNG7AttenTable()"
1667        Endif
1668        //just in case creating the tables fails....
1669        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) )
1670                Abort "Attenuator lookup waves could not be found. You must manually enter the absolute parameters"
1671        Endif
1672       
1673        //lookup the value by interpolating the wavelength
1674        //the attenuator must always be an integer
1675        Wave att = $attStr
1676        Wave attErrW = $attErrWStr
1677        Wave lam = $lamstr
1678        trans = interp(lambda,lam,att)
1679        atten_err = interp(lambda,lam,attErrW)
1680
1681// the error in the tables is % error. return the standard deviation instead
1682        atten_err = trans*atten_err/100
1683       
1684//      Print "trans = ",trans
1685//      Print "trans err = ",atten_err
1686       
1687        return trans
1688
1689End
1690
1691//returns the transmission of the attenuator (at NGA) given the attenuator number
1692//which must be an integer(to select the wave) and given the wavelength.
1693//the wavelength may be any value between 4 and 20 (A), and is interpolated
1694//between calibrated wavelengths for a given attenuator
1695//
1696// local function
1697//
1698// Mar 2010 - abs() added to attStr to account for ICE reporting -0.0001 as an attenuator position, which truncates to "-0"
1699//
1700// JAN 2013 -- a duplication of the NG7 table, needs to be updated after the attenuation factors
1701// are measured
1702//
1703// TODO_10m::::
1704//
1705Function LookupAttenNGA(lambda,attenNo,atten_err)
1706        Variable lambda, attenNo, &atten_err
1707       
1708        Variable trans
1709        String attStr="root:myGlobals:Attenuators:ngAatt"+num2str(trunc(abs(attenNo)))
1710        String attErrWStr="root:myGlobals:Attenuators:ngAatt"+num2str(trunc(abs(attenNo)))+"_err"
1711        String lamStr = "root:myGlobals:Attenuators:ngAlambda"
1712       
1713        if(attenNo == 0)
1714                return (1)              //no attenuation, return trans == 1
1715        endif
1716       
1717        if( (lambda < 4) || (lambda > 20 ) )
1718                Abort "Wavelength out of calibration range (4,20). You must manually enter the absolute parameters"
1719        Endif
1720       
1721        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) || !(WaveExists($attErrWStr)))
1722                Execute "MakeNGAAttenTable()"
1723        Endif
1724        //just in case creating the tables fails....
1725        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) )
1726                Abort "Attenuator lookup waves could not be found. You must manually enter the absolute parameters"
1727        Endif
1728       
1729        //lookup the value by interpolating the wavelength
1730        //the attenuator must always be an integer
1731        Wave att = $attStr
1732        Wave attErrW = $attErrWStr
1733        Wave lam = $lamstr
1734        trans = interp(lambda,lam,att)
1735        atten_err = interp(lambda,lam,attErrW)
1736
1737// the error in the tables is % error. return the standard deviation instead
1738        atten_err = trans*atten_err/100
1739       
1740//      Print "trans = ",trans
1741//      Print "trans err = ",atten_err
1742       
1743        return trans
1744
1745End
1746
1747// a utility function so that I can get the values from the command line
1748// since the atten_err is PBR
1749//
1750Function PrintAttenuation(instr,lam,attenNo)
1751        String instr
1752        Variable lam,attenNo
1753       
1754        Variable atten_err, attenFactor
1755       
1756        strswitch(instr)
1757                case "NG3":
1758                        attenFactor = LookupAttenNG3(lam,attenNo,atten_err)
1759                        break
1760                case "NG5":
1761                        //using NG7 lookup Table
1762                        attenFactor = LookupAttenNG7(lam,attenNo,atten_err)
1763                        break
1764                case "NG7":
1765                        attenFactor = LookupAttenNG7(lam,attenNo,atten_err)
1766                        break
1767                case "NGA":
1768                        Print "Using the NG7 table for NGA *** this needs to be updated ***"
1769                        attenFactor = LookupAttenNG7(lam,attenNo,atten_err)
1770                        break
1771                default:                                                       
1772                        //return error?
1773                        DoAlert 0, "No matching instrument -- PrintAttenuation"
1774                        attenFactor=1
1775        endswitch
1776
1777        Print "atten, err = ", attenFactor, atten_err
1778       
1779        return(0)
1780End
1781
1782
1783
1784//returns the proper attenuation factor based on the instrument (NG3, NG5, or NG7)
1785//NG5 values are taken from the NG7 tables (there is very little difference in the
1786//values, and NG5 attenuators have not been calibrated (as of 8/01)
1787//
1788// filestr is passed from TextRead[3] = the default directory
1789// lam is passed from RealsRead[26]
1790// AttenNo is passed from ReaslRead[3]
1791//
1792// Attenuation factor as defined here is <= 1
1793//
1794// HFIR can pass ("",1,attenuationFactor) and have this function simply
1795// spit back the attenuationFactor (that was read into rw[3])
1796//
1797// called by Correct.ipf, ProtocolAsPanel.ipf, Transmission.ipf
1798//
1799//
1800// as of March 2011, returns the error (one standard deviation) in the attenuation factor as the last parameter, by reference
1801Function AttenuationFactor(fileStr,lam,attenNo,atten_err)
1802        String fileStr
1803        Variable lam,attenNo, &atten_err
1804       
1805        Variable attenFactor=1,loc
1806        String instr=fileStr[1,3]       //filestr is "[NGnSANSn] " or "[NGnSANSnn]" (11 characters total)
1807       
1808        strswitch(instr)
1809                case "NG3":
1810                        attenFactor = LookupAttenNG3(lam,attenNo,atten_err)
1811                        break
1812                case "NG5":
1813                        //using NG7 lookup Table
1814                        attenFactor = LookupAttenNG7(lam,attenNo,atten_err)
1815                        break
1816                case "NG7":
1817                        attenFactor = LookupAttenNG7(lam,attenNo,atten_err)
1818                        break
1819                case "NGA":
1820                        Print "Using the NG7 table for NGA *** this needs to be updated ***"
1821                        attenFactor = LookupAttenNG7(lam,attenNo,atten_err)
1822                        break
1823                default:                                                       
1824                        //return error?
1825                        DoAlert 0, "No matching instrument -- PrintAttenuation"
1826                        attenFactor=1
1827        endswitch
1828//      print "instr, lambda, attenNo,attenFactor = ",instr,lam,attenNo,attenFactor
1829        return(attenFactor)
1830End
1831
1832//function called by the popups to get a file list of data that can be sorted
1833// this procedure simply removes the raw data files from the string - there
1834//can be lots of other junk present, but this is very fast...
1835//
1836// could also use the alternate procedure of keeping only file with the proper extension
1837//
1838// another possibility is to get a listing of the text files, but is unreliable on
1839// Windows, where the data file must be .txt (and possibly OSX)
1840//
1841// called by FIT_Ops.ipf, NSORT.ipf, PlotUtils.ipf
1842//
1843Function/S ReducedDataFileList(ctrlName)
1844        String ctrlName
1845
1846        String list="",newList="",item=""
1847        Variable num,ii
1848       
1849        //check for the path
1850        PathInfo catPathName
1851        if(V_Flag==0)
1852                DoAlert 0, "Data path does not exist - pick the data path from the button on the main panel"
1853                Return("")
1854        Endif
1855       
1856        list = IndexedFile(catpathName,-1,"????")
1857       
1858        list = RemoveFromList(ListMatch(list,"*.SA1*",";"), list, ";", 0)
1859        list = RemoveFromList(ListMatch(list,"*.SA2*",";"), list, ";", 0)
1860        list = RemoveFromList(ListMatch(list,"*.SA3*",";"), list, ";", 0)
1861        list = RemoveFromList(ListMatch(list,".*",";"), list, ";", 0)
1862        list = RemoveFromList(ListMatch(list,"*.pxp",";"), list, ";", 0)
1863        list = RemoveFromList(ListMatch(list,"*.DIV",";"), list, ";", 0)
1864        list = RemoveFromList(ListMatch(list,"*.GSP",";"), list, ";", 0)
1865        list = RemoveFromList(ListMatch(list,"*.MASK",";"), list, ";", 0)
1866
1867        //remove VAX version numbers
1868        list = RemoveVersNumsFromList(List)
1869        //sort
1870        newList = SortList(List,";",0)
1871
1872        return newlist
1873End
1874
1875// returns a list of raw data files in the catPathName directory on disk
1876// - list is SEMICOLON-delimited
1877//
1878// does it the "cheap" way, simply finding the ".SAn" in the file name
1879// = does not check for proper byte length.
1880//
1881// called by PatchFiles.ipf, Tile_2D.ipf
1882//
1883Function/S GetRawDataFileList()
1884       
1885        //make sure that path exists
1886        PathInfo catPathName
1887        if (V_flag == 0)
1888                Abort "Folder path does not exist - use Pick Path button on Main Panel"
1889        Endif
1890       
1891        String list=IndexedFile(catPathName,-1,"????")
1892        String newList="",item=""
1893        Variable num=ItemsInList(list,";"),ii
1894        for(ii=0;ii<num;ii+=1)
1895                item = StringFromList(ii, list  ,";")
1896                if( stringmatch(item,"*.sa1*") )
1897                        newlist += item + ";"
1898                endif
1899                if( stringmatch(item,"*.sa2*") )
1900                        newlist += item + ";"
1901                endif
1902                if( stringmatch(item,"*.sa3*") )
1903                        newlist += item + ";"
1904                endif
1905                //print "ii=",ii
1906        endfor
1907        newList = SortList(newList,";",0)
1908        return(newList)
1909End
1910
1911// Return the filename that represents the previous or next file.
1912// Input is current filename and increment.
1913// Increment should be -1 or 1
1914// -1 => previous file
1915// 1 => next file
1916Function/S GetPrevNextRawFile(curfilename, prevnext)
1917        String curfilename
1918        Variable prevnext
1919
1920        String filename
1921       
1922        //get the run number
1923        Variable num = GetRunNumFromFile(curfilename)
1924               
1925        //find the next specified file by number
1926        fileName = FindFileFromRunNumber(num+prevnext)
1927
1928        if(cmpstr(fileName,"")==0)
1929                //null return, do nothing
1930                fileName = FindFileFromRunNumber(num)
1931        Endif
1932
1933//      print "in FU "+filename
1934
1935        Return filename
1936End
1937
1938
Note: See TracBrowser for help on using the repository browser.