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

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

Added the attenuator table and flux values for the 10m SANS instrument as measured by John Barker. Other changes to the code for the 10m SANS appear to be complete, pending some more thorough testing.

File size: 66.2 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 = 4.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 = 4.0e-6         //per JGB 16-JAN-2013
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                                                     JAN 2013                                        4 microseconds
477//
478//
479// The day of the switch to ICE on NG7 was 25-FEB-2010 (per J. Krzywon)
480// The day of the switch to ICE on NG3 was 23-JUL-2009 (per C. Gagnon)
481//
482// so any data after these dates is to use the new dead time constant. The switch is made on the
483// data collection date.
484//
485//
486Function DetectorDeadtime(fileStr,detStr,[dateAndTimeStr])
487        String fileStr,detStr,dateAndTimeStr
488       
489        Variable deadtime
490        String instr=fileStr[1,3]       //filestr is "[NGnSANSn] " or "[NGnSANSnn]" (11 characters total)
491       
492        NVAR DeadtimeNG3_ILL = root:myGlobals:DeadtimeNG3_ILL           //pixel resolution in cm
493        NVAR DeadtimeNG5_ILL = root:myGlobals:DeadtimeNG5_ILL
494        NVAR DeadtimeNG7_ILL = root:myGlobals:DeadtimeNG7_ILL
495        NVAR DeadtimeNGA_ILL = root:myGlobals:DeadtimeNGA_ILL
496        NVAR DeadtimeNG3_ORNL_VAX = root:myGlobals:DeadtimeNG3_ORNL_VAX
497        NVAR DeadtimeNG3_ORNL_ICE = root:myGlobals:DeadtimeNG3_ORNL_ICE
498        NVAR DeadtimeNG5_ORNL = root:myGlobals:DeadtimeNG5_ORNL
499        NVAR DeadtimeNG7_ORNL_VAX = root:myGlobals:DeadtimeNG7_ORNL_VAX
500        NVAR DeadtimeNG7_ORNL_ICE = root:myGlobals:DeadtimeNG7_ORNL_ICE
501        NVAR DeadtimeNGA_ORNL_ICE = root:myGlobals:DeadtimeNGA_ORNL_ICE
502        NVAR DeadtimeDefault = root:myGlobals:DeadtimeDefault
503       
504        // if no date string is passed, default to the ICE values
505        if(strlen(dateAndTimeStr)==0)
506                dateAndTimeStr = "01-JAN-2011"          //dummy date to force to ICE values
507        endif
508       
509       
510        Variable NG3_to_ICE = ConvertVAXDay2secs("23-JUL-2009")
511        Variable NG7_to_ICE = ConvertVAXDay2secs("25-FEB-2010")
512        Variable fileTime = ConvertVAXDay2secs(dateAndTimeStr)
513
514       
515        strswitch(instr)
516                case "NG3":
517                        if(cmpstr(detStr, "ILL   ") == 0 )
518                                deadtime= DeadtimeNG3_ILL
519                        else
520                                if(fileTime > NG3_to_ICE)
521                                        deadtime = DeadtimeNG3_ORNL_ICE //detector is ordella-type, using ICE hardware
522                                else
523                                        deadtime = DeadtimeNG3_ORNL_VAX //detector is ordella-type
524                                endif
525                        endif
526                        break
527                case "NG5":
528                        if(cmpstr(detStr, "ILL   ") == 0 )
529                                deadtime= DeadtimeNG5_ILL
530                        else
531                                deadtime = DeadtimeNG5_ORNL     //detector is ordella-type
532                        endif
533                        break
534                case "NG7":
535                        if(cmpstr(detStr, "ILL   ") == 0 )
536                                deadtime= DeadtimeNG7_ILL
537                        else
538                                if(fileTime > NG7_to_ICE)
539                                        deadtime = DeadtimeNG7_ORNL_ICE //detector is ordella-type, using ICE hardware
540                                else
541                                        deadtime = DeadtimeNG7_ORNL_VAX //detector is ordella-type
542                                endif
543                        endif
544                        break
545                case "NGA":
546                        if(cmpstr(detStr, "ILL   ") == 0 )
547                                deadtime= DeadtimeNGA_ILL
548                        else
549                                deadtime = DeadtimeNGA_ORNL_ICE //detector is ordella-type, using ICE hardware
550                        endif
551                        Print "Using fictional values for NGA dead time"
552                        break
553                default:                                                       
554                        //return error?
555                        DoAlert 0, "no matching instrument DetectorDeadtime, using default"
556                        deadtime = DeadtimeDefault      //1e-6 seconds, typical for new ORNL detectors
557        endswitch
558       
559        return(deadtime)
560End
561
562// converts ONLY DD-MON-YYYY portion of the data collection time
563// to a number of seconds from midnight on 1/1/1904, as Igor likes to do
564//
565// dateAndTime is the full string of "dd-mon-yyyy hh:mm:ss" as returned by the function
566// getFileCreationDate(file)
567//
568Function ConvertVAXDay2secs(dateAndTime)
569        string dateAndTime
570       
571        Variable day,yr,mon,time_secs
572        string monStr
573
574        sscanf dateandtime,"%d-%3s-%4d",day,monStr,yr
575        mon = monStr2num(monStr)
576//      print yr,mon,day
577        time_secs = date2secs(yr,mon,day)
578
579        return(time_secs)
580end
581
582// dd-mon-yyyy hh:mm:ss -> seconds
583// the VAX uses 24 hr time for hh
584//
585Function ConvertVAXDateTime2secs(dateAndTime)
586        string dateAndTime
587       
588        Variable day,yr,mon,hh,mm,ss,time_secs
589        string str,monStr
590       
591        str=dateandtime
592        sscanf str,"%d-%3s-%4d %d:%d:%d",day,monStr,yr,hh,mm,ss
593        mon = monStr2num(monStr)
594//      print yr,mon,day,hh,mm,ss
595        time_secs = date2secs(yr,mon,day)
596        time_secs += hh*3600 + mm*60 + ss
597
598
599        return(time_secs)
600end
601
602// takes a month string and returns the corresponding number
603//
604Function monStr2num(monStr)
605        String monStr
606       
607        String list=";JAN;FEB;MAR;APR;MAY;JUN;JUL;AUG;SEP;OCT;NOV;DEC;"
608        return(WhichListItem(monStr, list ,";"))
609end
610
611
612//make a three character string of the run number
613//Moved to facility utils
614Function/S RunDigitString(num)
615        Variable num
616       
617        String numStr=""
618        if(num<10)
619                numStr = "00"+num2str(num)
620        else
621                if(num<100)
622                        numStr = "0"+num2str(num)
623                else
624                        numStr = num2str(num)
625                Endif
626        Endif
627        //Print "numstr = ",numstr
628        return(numstr)
629End
630
631//given a filename of a SANS data filename of the form
632//TTTTTnnn.SAn_TTT_Txxx
633//returns the prefix "TTTTT" as some number of characters
634//returns "" as an invalid file prefix
635//
636// NCNR-specifc, does not really belong here - but it's a beta procedure used for the
637// Combine Files Panel
638//
639Function/S GetPrefixStrFromFile(item)
640        String item
641        String invalid = ""     //"" is not a valid run prefix, since it's text
642        Variable num=-1
643       
644        //find the "dot"
645        String runStr=""
646        Variable pos = strsearch(item,".",0)
647        if(pos == -1)
648                //"dot" not found
649                return (invalid)
650        else
651                //found, skip the three characters preceeding it
652                if (pos <=3)
653                        //not enough characters
654                        return (invalid)
655                else
656                        runStr = item[0,pos-4]
657                        return (runStr)
658                Endif
659        Endif
660End
661
662
663
664
665/////VAX filename/Run number parsing utilities
666//
667// a collection of uilities for processing vax filenames
668//and processing lists (especially for display in popup menus)
669//
670//required to correctly account for VAX supplied version numbers, which
671//may or may not be removed by the ftp utility
672//
673// - parses lists of run numbers into real filenames
674// - selects proper detector constants
675//
676//**************************
677//
678//given a filename of a SANS data filename of the form
679//TTTTTnnn.SAn_TTT_Txxx
680//returns the run number "nnn" as a number
681//returns -1 as an invalid file number
682//
683// called by several ipfs
684//
685//
686Function GetRunNumFromFile(item)
687        String item
688        Variable invalid = -1   //negative numbers are invalid
689        Variable num=-1
690       
691        //find the "dot"
692        String runStr=""
693        Variable pos = strsearch(item,".",0)
694        if(pos == -1)
695                //"dot" not found
696                return (invalid)
697        else
698                //found, get the three characters preceeding it
699                if (pos <=2)
700                        //not enough characters
701                        return (invalid)
702                else
703                        runStr = item[pos-3,pos-1]
704                        //convert to a number
705                        num = str2num(runStr)
706                        //if valid, return it
707                        if (num == NaN)
708                                //3 characters were not a number
709                                return (invalid)
710                        else
711                                //run was OK
712                                return (num)
713                        Endif
714                Endif
715        Endif
716End
717
718//given a filename of a SANS data filename of the form
719//TTTTTnnn.SAn_TTT_Txxx
720//returns the run number "nnn" as a STRING of THREE characters
721//returns "ABC" as an invalid file number
722//
723// local function to aid in locating files by run number
724//
725Function/S GetRunNumStrFromFile(item)
726        String item
727        String invalid = "ABC"  //"ABC" is not a valid run number, since it's text
728        Variable num=-1
729       
730        //find the "dot"
731        String runStr=""
732        Variable pos = strsearch(item,".",0)
733        if(pos == -1)
734                //"dot" not found
735                return (invalid)
736        else
737                //found, get the three characters preceeding it
738                if (pos <=2)
739                        //not enough characters
740                        return (invalid)
741                else
742                        runStr = item[pos-3,pos-1]
743                        return (runStr)
744                Endif
745        Endif
746End
747
748//returns a string containing the full path to the file containing the
749//run number "num". The null string is returned if no valid file can be found
750//the path "catPathName" used and is hard-wired, will abort if this path does not exist
751//the file returned will be a RAW SANS data file, other types of files are
752//filtered out.
753//
754// called by Buttons.ipf and Transmission.ipf, and locally by parsing routines
755//
756Function/S FindFileFromRunNumber(num)
757        Variable num
758       
759        String fullName="",partialName="",item=""
760        //get list of raw data files in folder that match "num" (add leading zeros)
761        if( (num>999) || (num<=0) )
762                //Print "error in  FindFileFromRunNumber(num), file number too large or too small"
763                Return ("")
764        Endif
765        //make a three character string of the run number
766        String numStr=""
767        if(num<10)
768                numStr = "00"+num2str(num)
769        else
770                if(num<100)
771                        numStr = "0"+num2str(num)
772                else
773                        numStr = num2str(num)
774                Endif
775        Endif
776        //Print "numstr = ",numstr
777       
778        //make sure that path exists
779        PathInfo catPathName
780        String path = S_path
781        if (V_flag == 0)
782                Abort "folder path does not exist - use Pick Path button"
783        Endif
784        String list="",newList="",testStr=""
785       
786        list = IndexedFile(catPathName,-1,"????")       //get all files in folder
787        //find (the) one with the number in the run # location in the name
788        Variable numItems,ii,runFound,isRAW
789        numItems = ItemsInList(list,";")                //get the new number of items in the list
790        ii=0
791        do
792                //parse through the list in this order:
793                // 1 - does item contain run number (as a string) "TTTTTnnn.SAn_XXX_Tyyy"
794                // 2 - exclude by isRaw? (to minimize disk access)
795                item = StringFromList(ii, list  ,";" )
796                if(strlen(item) != 0)
797                        //find the run number, if it exists as a three character string
798                        testStr = GetRunNumStrFromFile(item)
799                        runFound= cmpstr(numStr,testStr)        //compare the three character strings, 0 if equal
800                        if(runFound == 0)
801                                //the run Number was found
802                                //build valid filename
803                                partialName = FindValidFileName(item)
804                                if(strlen(partialName) != 0)            //non-null return from FindValidFileName()
805                                        fullName = path + partialName
806                                        //check if RAW, if so,this must be the file!
807                                        isRAW = CheckIfRawData(fullName)
808                                        if(isRaw)
809                                                //stop here
810                                                return(fullname)
811                                        Endif
812                                Endif
813                        Endif
814                Endif
815                ii+=1
816        while(ii<numItems)              //process all items in list
817        Return ("")     //null return if file not found in list
818End
819
820//function to test a binary file to see if it is a RAW binary SANS file
821//first checks the total bytes in the file (which for raw data is 33316 bytes)
822//**note that the "DIV" file will also show up as a raw file by the run field
823//should be listed in CAT/SHORT and in patch windows
824//
825//Function then checks the file fname (full path:file) for "RAW" run.type field
826//if not found, the data is not raw data and zero is returned
827//
828// called by many procedures (both external and local)
829//
830Function CheckIfRawData(fname)
831        String fname
832       
833        Variable refnum,totalBytes
834        String testStr=""
835       
836        Open/R/T="????TEXT" refNum as fname
837        if(strlen(s_filename) == 0)     //user cancel (/Z not used, so V_flag not set)
838                return(0)
839        endif
840       
841        //get the total number of bytes in the file
842        FStatus refNum
843        totalBytes = V_logEOF
844        //Print totalBytes
845        if(totalBytes < 100)
846                Close refNum
847                return(0)               //not a raw file
848        endif
849        FSetPos refNum,75
850        FReadLine/N=3 refNum,testStr
851        Close refNum
852       
853        if(totalBytes == 33316 && ( cmpstr(testStr,"RAW")==0 ||  cmpstr(testStr,"SIM")==0))
854                //true, is raw data file
855                Return(1)
856        else
857                //some other file
858                Return(0)
859        Endif
860End
861
862//function to test a file to see if it is a DIV file
863//
864// returns truth 0/1
865//
866// called by many procedures (both external and local)
867//
868Function CheckIfDIVData(fname)
869        String fname
870       
871
872        Variable refnum,totalBytes
873//      String testStr=""
874       
875        Open/R/T="????TEXT" refNum as fname
876        if(strlen(s_filename) == 0)     //user cancel (/Z not used, so V_flag not set)
877                return(0)
878        endif
879       
880        //get the total number of bytes in the file
881        FStatus refNum
882        totalBytes = V_logEOF
883        //Print totalBytes
884        if(totalBytes < 100)
885                Close refNum
886                return(0)               //not a raw file
887        endif
888//      FSetPos refNum,75
889//      FReadLine/N=3 refNum,testStr
890        Close refNum
891       
892        if(totalBytes == 66116)         // && ( cmpstr(testStr,"RAW")==0 ||  cmpstr(testStr,"SIM")==0))
893                //true, is raw data file
894                Return(1)
895        else
896                //some other file
897                Return(0)
898        Endif
899
900End
901
902//function to check the header of a raw data file (full path specified by fname)
903//checks the field of the x-position of the beamstop during data collection
904//if the x-position is more negative (farther to the left) than xTol(input)
905//the the beamstop is "out" and the file is a transmission run and not a scattering run
906//xtol typically set at -5 (cm) - trans runs have bs(x) at -10 to -15 cm
907// function returns 1 if beamstop is out, 0 if beamstop is in
908//
909// tolerance is set as a global value "root:myGlobals:BeamstopXTol"
910//
911// called by Transmission.ipf, CatVSTable.ipf, NSORT.ipf
912//
913Function isTransFile(fName)
914        String fname
915       
916        Variable refnum,xpos
917        NVAR xTol = root:myGlobals:BeamstopXTol
918       
919        //pos = 369, read one real value
920       
921        SetDataFolder root:
922        String GBLoadStr="GBLoadWave/O/N=tempGBwave/T={2,2}/J=2/W=1/Q"
923        String strToExecute=""
924        // 1 R*4 value
925        strToExecute = GBLoadStr + "/S=368/U=1" + "\"" + fname + "\""
926        Execute strToExecute
927        Wave w=$"root:tempGBWave0"
928        xPos = w[0]
929        KillWaves/Z w
930        //Print "xPos = ",xpos
931       
932        if(xpos<=xTol)
933                //xpos is farther left (more negative) than xtol (currently -5 cm)
934                Return(1)
935        else
936                //some other file
937                Return(0)
938        Endif
939End
940
941
942//function to remove all spaces from names when searching for filenames
943//the filename (as saved) will never have interior spaces (TTTTTnnn_AB _Bnnn)
944//but the text field in the header WILL, if less than 3 characters were used for the
945//user's initials, and can have leading spaces if prefix was less than 5 characters
946//
947//returns a string identical to the original string, except with the interior spaces removed
948//
949// local function for file name manipulation
950//
951Function/S RemoveAllSpaces(str)
952        String str
953       
954        String tempstr = str
955        Variable ii,spc,len             //should never be more than 2 or 3 trailing spaces in a filename
956        ii=0
957        do
958                len = strlen(tempStr)
959                spc = strsearch(tempStr," ",0)          //is the last character a space?
960                if (spc == -1)
961                        break           //no more spaces found, get out
962                endif
963                str = tempstr
964                tempStr = str[0,(spc-1)] + str[(spc+1),(len-1)] //remove the space from the string
965        While(1)        //should never be more than 2 or 3
966       
967        If(strlen(tempStr) < 1)
968                tempStr = ""            //be sure to return a null string if problem found
969        Endif
970       
971        //Print strlen(tempstr)
972       
973        Return(tempStr)
974               
975End
976
977
978//Function attempts to find valid filename from partial name by checking for
979// the existence of the file on disk.
980// - checks as is
981// - adds ";vers" for possible VAX files
982// - strips spaces
983// - permutations of upper/lowercase
984//
985// added 11/99 - uppercase and lowercase versions of the file are tried, if necessary
986// since from marquee, the filename field (textread[0]) must be used, and can be a mix of
987// upper/lowercase letters, while the filename on the server (should) be all caps
988// now makes repeated calls to ValidFileString()
989//
990// returns a valid filename (No path prepended) or a null string
991//
992// called by any functions, both external and local
993//
994Function/S FindValidFilename(partialName)
995        String PartialName
996       
997        String retStr=""
998       
999        //try name with no changes - to allow for ABS files that have spaces in the names 12APR04
1000        retStr = ValidFileString(partialName)
1001        if(cmpstr(retStr,"") !=0)
1002                //non-null return
1003                return(retStr)
1004        Endif
1005       
1006        //if the partial name is derived from the file header, there can be spaces at the beginning
1007        //or in the middle of the filename - depending on the prefix and initials used
1008        //
1009        //remove any leading spaces from the name before starting
1010        partialName = RemoveAllSpaces(partialName)
1011       
1012        //try name with no spaces
1013        retStr = ValidFileString(partialName)
1014        if(cmpstr(retStr,"") !=0)
1015                //non-null return
1016                return(retStr)
1017        Endif
1018       
1019        //try all UPPERCASE
1020        partialName = UpperStr(partialName)
1021        retStr = ValidFileString(partialName)
1022        if(cmpstr(retStr,"") !=0)
1023                //non-null return
1024                return(retStr)
1025        Endif
1026       
1027        //try all lowercase (ret null if failure)
1028        partialName = LowerStr(partialName)
1029        retStr = ValidFileString(partialName)
1030        if(cmpstr(retStr,"") !=0)
1031                //non-null return
1032                return(retStr)
1033        else
1034                return(retStr)
1035        Endif
1036End
1037
1038// Function checks for the existence of a file
1039// partialName;vers (to account for VAX filenaming conventions)
1040// The partial name is tried first with no version number
1041//
1042// *** the PATH is hard-wired to catPathName (which is assumed to exist)
1043// version numers up to ;10 are tried
1044// only the "name;vers" is returned if successful. The path is not prepended
1045//
1046// local function
1047//
1048Function/S ValidFileString(partialName)
1049        String partialName
1050       
1051        String tempName = "",msg=""
1052        Variable ii,refnum
1053       
1054        ii=0
1055        do
1056                if(ii==0)
1057                        //first pass, try the partialName
1058                        tempName = partialName
1059                        Open/Z/R/T="????TEXT"/P=catPathName refnum tempName     //Does open file (/Z flag)
1060                        if(V_flag == 0)
1061                                //file exists
1062                                Close refnum            //YES needed,
1063                                break
1064                        endif
1065                else
1066                        tempName = partialName + ";" + num2str(ii)
1067                        Open/Z/R/T="????TEXT"/P=catPathName refnum tempName
1068                        if(V_flag == 0)
1069                                //file exists
1070                                Close refnum
1071                                break
1072                        endif
1073                Endif
1074                ii+=1
1075                //print "ii=",ii
1076        while(ii<11)
1077        //go get the selected bits of information, using tempName, which exists
1078        if(ii>=11)
1079                //msg = partialName + " not found. is version number > 11?"
1080                //DoAlert 0, msg
1081                //PathInfo catPathName
1082                //Print S_Path
1083                Return ("")             //use null string as error condition
1084        Endif
1085       
1086        Return (tempName)
1087End
1088
1089//returns a string containing filename (WITHOUT the ;vers)
1090//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
1091//with the folders separated by colons
1092//
1093// called by MaskUtils.ipf, ProtocolAsPanel.ipf, WriteQIS.ipf
1094//
1095Function/S GetFileNameFromPathNoSemi(fullPath)
1096        String fullPath
1097       
1098        Variable offset1,offset2
1099        String filename=""
1100        //String PartialPath
1101        offset1 = 0
1102        do
1103                offset2 = StrSearch(fullPath, ":", offset1)
1104                if (offset2 == -1)                              // no more colons ?
1105                        fileName = FullPath[offset1,strlen(FullPath) ]
1106                        //PartialPath = FullPath[0, offset1-1]
1107                        break
1108                endif
1109                offset1 = offset2+1
1110        while (1)
1111       
1112        //remove version number from name, if it's there - format should be: filename;N
1113        filename =  StringFromList(0,filename,";")              //returns null if error
1114       
1115        Return filename
1116End
1117
1118//returns a string containing filename (INCLUDING the ;vers)
1119//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
1120//with the folders separated by colons
1121//
1122// local, currently unused
1123//
1124Function/S GetFileNameFromPathKeepSemi(fullPath)
1125        String fullPath
1126       
1127        Variable offset1,offset2
1128        String filename
1129        //String PartialPath
1130        offset1 = 0
1131        do
1132                offset2 = StrSearch(fullPath, ":", offset1)
1133                if (offset2 == -1)                              // no more colons ?
1134                        fileName = FullPath[offset1,strlen(FullPath) ]
1135                        //PartialPath = FullPath[0, offset1-1]
1136                        break
1137                endif
1138                offset1 = offset2+1
1139        while (1)
1140       
1141        //keep version number from name, if it's there - format should be: filename;N
1142       
1143        Return filename
1144End
1145
1146//given the full path and filename (fullPath), strips the data path
1147//(Mac-style, separated by colons) and returns this path
1148//this partial path is the same string that would be returned from PathInfo, for example
1149//
1150// - allows the user to save to a different path than catPathName
1151//
1152// called by WriteQIS.ipf
1153//
1154Function/S GetPathStrFromfullName(fullPath)
1155        String fullPath
1156       
1157        Variable offset1,offset2
1158        //String filename
1159        String PartialPath
1160        offset1 = 0
1161        do
1162                offset2 = StrSearch(fullPath, ":", offset1)
1163                if (offset2 == -1)                              // no more colons ?
1164                        //fileName = FullPath[offset1,strlen(FullPath) ]
1165                        PartialPath = FullPath[0, offset1-1]
1166                        break
1167                endif
1168                offset1 = offset2+1
1169        while (1)
1170       
1171        Return PartialPath
1172End
1173
1174//given the VAX filename, pull off the first 8 characters to make a valid
1175//file string that can be used for naming averaged 1-d files
1176//
1177// called by ProtocolAsPanel.ipf and Tile_2D.ipf
1178//
1179Function/S GetNameFromHeader(fullName)
1180        String fullName
1181        String temp, newName = ""
1182        Variable spc,ii=0
1183       
1184        //filename is 20 characters NNNNNxxx.SAn_NNN_NNN
1185        //want the first 8 characters, NNNNNxxx, then strip off any spaces at the beginning
1186        //NNNNN was entered as less than 5 characters
1187        //returns a null string if no name can be found
1188        do
1189                temp = fullname[ii,7]           //characters ii,7 of the name
1190                spc = strsearch(temp," ",0)
1191                if (spc == -1)
1192                        break           //no more spaces found
1193                endif
1194                ii+=1
1195        While(ii<8)
1196       
1197        If(strlen(temp) < 1)
1198                newName = ""            //be sure to return a null string if problem found
1199        else
1200                newName = temp
1201        Endif
1202       
1203        Return(newName)
1204End
1205
1206//list (input) is a list, typically returned from IndexedFile()
1207//which is semicolon-delimited, and may contain filenames from the VAX
1208//that contain version numbers, where the version number appears as a separate list item
1209//(and also as a non-existent file)
1210//these numbers must be purged from the list, especially for display in a popup
1211//or list processing of filenames
1212//the function returns the list, cleaned of version numbers (up to 11)
1213//raw data files will typically never have a version number other than 1.
1214//
1215// if there are no version numbers in the list, the input list is returned
1216//
1217// called by CatVSTable.ipf, NSORT.ipf, Transmission.ipf, WorkFileUtils.ipf
1218//
1219Function/S RemoveVersNumsFromList(list)
1220        String list
1221       
1222        //get rid of version numbers first (up to 11)
1223        Variable ii,num
1224        String item
1225        num = ItemsInList(list,";")
1226        ii=1
1227        do
1228                item = num2str(ii)
1229                list = RemoveFromList(item, list ,";" )
1230                ii+=1
1231        while(ii<12)
1232       
1233        return (list)
1234End
1235
1236//input is a list of run numbers, and output is a list of filenames (not the full path)
1237//*** input list must be COMMA delimited***
1238//output is equivalent to selecting from the CAT table
1239//if some or all of the list items are valid filenames, keep them...
1240//if an error is encountered, notify of the offending element and return a null list
1241//
1242//output is COMMA delimited
1243//
1244// this routine is expecting that the "ask", "none" special cases are handled elsewhere
1245//and not passed here
1246//
1247// called by Marquee.ipf, MultipleReduce.ipf, ProtocolAsPanel.ipf
1248//
1249Function/S ParseRunNumberList(list)
1250        String list
1251       
1252        String newList="",item="",tempStr=""
1253        Variable num,ii,runNum
1254       
1255        //expand number ranges, if any
1256        list = ExpandNumRanges(list)
1257       
1258        num=itemsinlist(list,",")
1259       
1260        for(ii=0;ii<num;ii+=1)
1261                //get the item
1262                item = StringFromList(ii,list,",")
1263                //is it already a valid filename?
1264                tempStr=FindValidFilename(item) //returns filename if good, null if error
1265                if(strlen(tempstr)!=0)
1266                        //valid name, add to list
1267                        //Print "it's a file"
1268                        newList += tempStr + ","
1269                else
1270                        //not a valid name
1271                        //is it a number?
1272                        runNum=str2num(item)
1273                        //print runnum
1274                        if(numtype(runNum) != 0)
1275                                //not a number -  maybe an error                       
1276                                DoAlert 0,"List item "+item+" is not a valid run number or filename. Please enter a valid number or filename."
1277                                return("")
1278                        else
1279                                //a run number or an error
1280                                tempStr = GetFileNameFromPathNoSemi( FindFileFromRunNumber(runNum) )
1281                                if(strlen(tempstr)==0)
1282                                        //file not found, error
1283                                        DoAlert 0,"List item "+item+" is not a valid run number. Please enter a valid number."
1284                                        return("")
1285                                else
1286                                        newList += tempStr + ","
1287                                endif
1288                        endif
1289                endif
1290        endfor          //loop over all items in list
1291       
1292        return(newList)
1293End
1294
1295//takes a comma delimited list that MAY contain number range, and
1296//expands any range of run numbers into a comma-delimited list...
1297//and returns the new list - if not a range, return unchanged
1298//
1299// local function
1300//
1301Function/S ExpandNumRanges(list)
1302        String list
1303       
1304        String newList="",dash="-",item,str
1305        Variable num,ii,hasDash
1306       
1307        num=itemsinlist(list,",")
1308//      print num
1309        for(ii=0;ii<num;ii+=1)
1310                //get the item
1311                item = StringFromList(ii,list,",")
1312                //does it contain a dash?
1313                hasDash = strsearch(item,dash,0)                //-1 if no dash found
1314                if(hasDash == -1)
1315                        //not a range, keep it in the list
1316                        newList += item + ","
1317                else
1318                        //has a dash (so it's a range), expand (or add null)
1319                        newList += ListFromDash(item)           
1320                endif
1321        endfor
1322       
1323        return newList
1324End
1325
1326//be sure to add a trailing comma to the return string...
1327//
1328// local function
1329//
1330Function/S ListFromDash(item)
1331        String item
1332       
1333        String numList="",loStr="",hiStr=""
1334        Variable lo,hi,ii
1335       
1336        loStr=StringFromList(0,item,"-")        //treat the range as a list
1337        hiStr=StringFromList(1,item,"-")
1338        lo=str2num(loStr)
1339        hi=str2num(hiStr)
1340        if( (numtype(lo) != 0) || (numtype(hi) !=0 ) || (lo > hi) )
1341                numList=""
1342                return numList
1343        endif
1344        for(ii=lo;ii<=hi;ii+=1)
1345                numList += num2str(ii) + ","
1346        endfor
1347       
1348        Return numList
1349End
1350
1351
1352////////Transmission
1353//******************
1354//lookup tables for attenuator transmissions
1355//NG3 and NG7 attenuators are physically different, so the transmissions are slightly different
1356//NG1 - (8m SANS) is not supported
1357//
1358// new calibration done June 2007, John Barker
1359//
1360Proc MakeNG3AttenTable()
1361
1362        NewDataFolder/O root:myGlobals:Attenuators
1363        //do explicitly to avoid data folder problems, redundant, but it must work without fail
1364        Variable num=10         //10 needed for tables after June 2007
1365
1366        Make/O/N=(num) root:myGlobals:Attenuators:ng3att0
1367        Make/O/N=(num) root:myGlobals:Attenuators:ng3att1
1368        Make/O/N=(num) root:myGlobals:Attenuators:ng3att2
1369        Make/O/N=(num) root:myGlobals:Attenuators:ng3att3
1370        Make/O/N=(num) root:myGlobals:Attenuators:ng3att4
1371        Make/O/N=(num) root:myGlobals:Attenuators:ng3att5
1372        Make/O/N=(num) root:myGlobals:Attenuators:ng3att6
1373        Make/O/N=(num) root:myGlobals:Attenuators:ng3att7
1374        Make/O/N=(num) root:myGlobals:Attenuators:ng3att8
1375        Make/O/N=(num) root:myGlobals:Attenuators:ng3att9
1376        Make/O/N=(num) root:myGlobals:Attenuators:ng3att10
1377       
1378        // and a wave for the errors at each attenuation factor
1379        Make/O/N=(num) root:myGlobals:Attenuators:ng3att0_err
1380        Make/O/N=(num) root:myGlobals:Attenuators:ng3att1_err
1381        Make/O/N=(num) root:myGlobals:Attenuators:ng3att2_err
1382        Make/O/N=(num) root:myGlobals:Attenuators:ng3att3_err
1383        Make/O/N=(num) root:myGlobals:Attenuators:ng3att4_err
1384        Make/O/N=(num) root:myGlobals:Attenuators:ng3att5_err
1385        Make/O/N=(num) root:myGlobals:Attenuators:ng3att6_err
1386        Make/O/N=(num) root:myGlobals:Attenuators:ng3att7_err
1387        Make/O/N=(num) root:myGlobals:Attenuators:ng3att8_err
1388        Make/O/N=(num) root:myGlobals:Attenuators:ng3att9_err
1389        Make/O/N=(num) root:myGlobals:Attenuators:ng3att10_err
1390       
1391       
1392        //each wave has 10 elements, the transmission of att# at the wavelengths
1393        //lambda = 4,5,6,7,8,10,12,14,17,20 (4 A and 20 A are extrapolated values)
1394        Make/O/N=(num) root:myGlobals:Attenuators:ng3lambda={4,5,6,7,8,10,12,14,17,20}
1395       
1396        // new calibration done June 2007, John Barker
1397        root:myGlobals:Attenuators:ng3att0 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
1398        root:myGlobals:Attenuators:ng3att1 = {0.444784,0.419,0.3935,0.3682,0.3492,0.3132,0.2936,0.2767,0.2477,0.22404}
1399        root:myGlobals:Attenuators:ng3att2 = {0.207506,0.1848,0.1629,0.1447,0.1292,0.1056,0.09263,0.08171,0.06656,0.0546552}
1400        root:myGlobals:Attenuators:ng3att3 = {0.092412,0.07746,0.06422,0.05379,0.04512,0.03321,0.02707,0.02237,0.01643,0.0121969}
1401        root:myGlobals:Attenuators:ng3att4 = {0.0417722,0.03302,0.02567,0.02036,0.01604,0.01067,0.00812,0.006316,0.00419,0.00282411}
1402        root:myGlobals:Attenuators:ng3att5 = {0.0187129,0.01397,0.01017,0.007591,0.005668,0.003377,0.002423,0.001771,0.001064,0.000651257}
1403        root:myGlobals:Attenuators:ng3att6 = {0.00851048,0.005984,0.004104,0.002888,0.002029,0.001098,0.0007419,0.0005141,0.000272833,0.000150624}
1404        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}
1405        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}
1406        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}
1407        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}
1408 
1409  // percent errors as measured, May 2007 values
1410  // zero error for zero attenuators, appropriate average values put in for unknown values
1411        root:myGlobals:Attenuators:ng3att0_err = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
1412        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}
1413        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}
1414        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}
1415        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}
1416        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}
1417        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}
1418        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}
1419        root:myGlobals:Attenuators:ng3att8_err = {0.7,0.705,0.927,0.503,0.691,1.27,1,1,1,1}
1420        root:myGlobals:Attenuators:ng3att9_err = {1,0.862,1.172,0.799,1.104,1.891,1.5,1.5,1.5,1.5}
1421        root:myGlobals:Attenuators:ng3att10_err = {1.5,1.054,1.435,1.354,1.742,2,2,2,2,2}
1422 
1423 
1424  //old tables, pre-June 2007
1425//      Make/O/N=9 root:myGlobals:Attenuators:ng3lambda={5,6,7,8,10,12,14,17,20}
1426//      root:myGlobals:Attenuators:ng3att0 = {1, 1, 1, 1, 1, 1, 1, 1,1 }
1427//      root:myGlobals:Attenuators:ng3att1 = {0.421, 0.394, 0.371, 0.349, 0.316, 0.293, 0.274, 0.245,0.220}
1428//      root:myGlobals:Attenuators:ng3att2 = {0.187, 0.164, 0.145, 0.130, 0.106, 0.0916, 0.0808, 0.0651,0.0531}
1429//      root:myGlobals:Attenuators:ng3att3 = {0.0777, 0.0636, 0.0534, 0.0446, 0.0330, 0.0262, 0.0217, 0.0157 ,0.0116}
1430//      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}
1431//      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}
1432//      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}
1433//      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}
1434//      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}
1435//      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}
1436//      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}
1437
1438End
1439
1440// new calibration done June 2007, John Barker
1441Proc MakeNG7AttenTable()
1442
1443        NewDataFolder/O root:myGlobals:Attenuators
1444       
1445        Variable num=10         //10 needed for tables after June 2007
1446       
1447        Make/O/N=(num) root:myGlobals:Attenuators:ng7att0
1448        Make/O/N=(num) root:myGlobals:Attenuators:ng7att1
1449        Make/O/N=(num) root:myGlobals:Attenuators:ng7att2
1450        Make/O/N=(num) root:myGlobals:Attenuators:ng7att3
1451        Make/O/N=(num) root:myGlobals:Attenuators:ng7att4
1452        Make/O/N=(num) root:myGlobals:Attenuators:ng7att5
1453        Make/O/N=(num) root:myGlobals:Attenuators:ng7att6
1454        Make/O/N=(num) root:myGlobals:Attenuators:ng7att7
1455        Make/O/N=(num) root:myGlobals:Attenuators:ng7att8
1456        Make/O/N=(num) root:myGlobals:Attenuators:ng7att9
1457        Make/O/N=(num) root:myGlobals:Attenuators:ng7att10
1458       
1459        // and a wave for the errors at each attenuation factor
1460        Make/O/N=(num) root:myGlobals:Attenuators:ng7att0_err
1461        Make/O/N=(num) root:myGlobals:Attenuators:ng7att1_err
1462        Make/O/N=(num) root:myGlobals:Attenuators:ng7att2_err
1463        Make/O/N=(num) root:myGlobals:Attenuators:ng7att3_err
1464        Make/O/N=(num) root:myGlobals:Attenuators:ng7att4_err
1465        Make/O/N=(num) root:myGlobals:Attenuators:ng7att5_err
1466        Make/O/N=(num) root:myGlobals:Attenuators:ng7att6_err
1467        Make/O/N=(num) root:myGlobals:Attenuators:ng7att7_err
1468        Make/O/N=(num) root:myGlobals:Attenuators:ng7att8_err
1469        Make/O/N=(num) root:myGlobals:Attenuators:ng7att9_err
1470        Make/O/N=(num) root:myGlobals:Attenuators:ng7att10_err 
1471       
1472        //NG7 wave has 10 elements, the transmission of att# at the wavelengths
1473        //lambda =4, 5,6,7,8,10,12,14,17,20
1474        // note that some of the higher attenuations and ALL of the 4 A and 20A data is interpolated
1475        // none of these values are expected to be used in reality since the flux would be too low in practice
1476        Make/O/N=(num) root:myGlobals:Attenuators:ng7lambda={4,5,6,7,8,10,12,14,17,20}
1477
1478// New calibration, June 2007, John Barker
1479        root:myGlobals:Attenuators:ng7att0 = {1, 1, 1, 1, 1, 1, 1, 1 ,1,1}     
1480        root:myGlobals:Attenuators:ng7att1 = {0.448656,0.4192,0.3925,0.3661,0.3458,0.3098,0.2922,0.2738,0.2544,0.251352}
1481        root:myGlobals:Attenuators:ng7att2 = {0.217193,0.1898,0.1682,0.148,0.1321,0.1076,0.0957,0.08485,0.07479,0.0735965}
1482        root:myGlobals:Attenuators:ng7att3 = {0.098019,0.07877,0.06611,0.05429,0.04548,0.03318,0.02798,0.0234,0.02004,0.0202492}
1483        root:myGlobals:Attenuators:ng7att4 = {0.0426904,0.03302,0.02617,0.02026,0.0158,0.01052,0.008327,0.006665,0.005745,0.00524807}
1484        root:myGlobals:Attenuators:ng7att5 = {0.0194353,0.01398,0.01037,0.0075496,0.005542,0.003339,0.002505,0.001936,0.001765,0.00165959}
1485        root:myGlobals:Attenuators:ng7att6 = {0.00971666,0.005979,0.004136,0.002848,0.001946,0.001079,0.0007717,0.000588,0.000487337,0.000447713}
1486        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}
1487        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}
1488        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}
1489        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}
1490
1491  // percent errors as measured, May 2007 values
1492  // zero error for zero attenuators, appropriate average values put in for unknown values
1493        root:myGlobals:Attenuators:ng7att0_err = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
1494        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}
1495        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}
1496        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}
1497        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}
1498        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}
1499        root:myGlobals:Attenuators:ng7att6_err = {0.6,0.501,0.6136,0.528,0.8796,1.708,0.782,0.874,1,1}
1500        root:myGlobals:Attenuators:ng7att7_err = {0.8,0.697,0.9149,0.583,1.173,2.427,1.242,2,2,2}
1501        root:myGlobals:Attenuators:ng7att8_err = {1,0.898,1.24,0.696,1.577,3.412,3,3,3,3}
1502        root:myGlobals:Attenuators:ng7att9_err = {1.5,1.113,1.599,1.154,2.324,4.721,5,5,5,5}
1503        root:myGlobals:Attenuators:ng7att10_err = {1.5,1.493,5,5,5,5,5,5,5,5} 
1504 
1505
1506// Pre-June 2007 calibration values - do not use these anymore 
1507////    root:myGlobals:Attenuators:ng7att0 = {1, 1, 1, 1, 1, 1, 1, 1 ,1}
1508////    root:myGlobals:Attenuators:ng7att1 = {0.418, 0.393, 0.369, 0.347, 0.313, 0.291, 0.271, 0.244, 0.219 }
1509////    root:myGlobals:Attenuators:ng7att2 = {0.189, 0.167, 0.148, 0.132, 0.109, 0.0945, 0.0830, 0.0681, 0.0560}
1510////    root:myGlobals:Attenuators:ng7att3 = {0.0784, 0.0651, 0.0541, 0.0456, 0.0340, 0.0273, 0.0223, 0.0164 , 0.0121}
1511////    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}
1512////    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}
1513////    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}
1514////    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}
1515////    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}
1516////    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}
1517////    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}
1518End
1519
1520
1521// JAN 2013 -- Using John's measured values from 23 JAN 2013
1522//
1523// there are 13 discrete wavelengths in ngALambda = 13 (only 10 used for 30m)
1524// there are only 9 attenuators, not 10 as in the 30m
1525//
1526Proc MakeNGAAttenTable()
1527
1528        NewDataFolder/O root:myGlobals:Attenuators
1529       
1530        Variable num=13         //13 needed for tables to cover 3A - 30A
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 13 elements, the transmission of att# at the wavelengths
1558        //lambda = 3A to 30A
1559        // note that some of the higher attenuations and ALL of the 30A 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={3,4,5,6,7,8,10,12,14,17,20,25,30}
1562
1563// New calibration, Jan 2013 John Barker
1564        root:myGlobals:Attenuators:ngAatt0 = {1,1,1,1,1,1,1,1,1,1,1,1,1}       
1565        root:myGlobals:Attenuators:ngAatt1 = {0.522,0.476,0.42007,0.39298,0.36996,0.35462,0.31637,0.29422,0.27617,0.24904,0.22263,0.18525,0.15}
1566        root:myGlobals:Attenuators:ngAatt2 = {0.27046,0.21783,0.17405,0.15566,0.13955,0.1272,0.10114,0.087289,0.077363,0.063607,0.051098,0.0357,0.023}
1567        root:myGlobals:Attenuators:ngAatt3 = {0.12601,0.090906,0.064869,0.054644,0.046916,0.041169,0.028926,0.023074,0.019276,0.014244,0.01021,0.006029,0.0033}
1568        root:myGlobals:Attenuators:ngAatt4 = {0.057782,0.037886,0.024727,0.019499,0.015719,0.013041,0.0080739,0.0059418,0.0046688,0.0031064,0.0020001,0.0010049,0.0005}
1569        root:myGlobals:Attenuators:ngAatt5 = {0.026627,0.016169,0.0096679,0.0071309,0.0052982,0.0040951,0.0021809,0.001479,0.001096,0.00066564,0.00039384,0.0002,9e-05}
1570        root:myGlobals:Attenuators:ngAatt6 = {0.0091671,0.0053041,0.0029358,0.0019376,0.0013125,0.00096946,0.00042126,0.0002713,0.00019566,0.00011443,5e-05,3e-05,1.2e-05}
1571        root:myGlobals:Attenuators:ngAatt7 = {0.0017971,0.00089679,0.00040572,0.0002255,0.00013669,8.7739e-05,3.3373e-05,2.0759e-05,1.5624e-05,1e-05,8e-06,4e-06,2.1e-06}
1572        root:myGlobals:Attenuators:ngAatt8 = {0.00033646,0.00012902,4.6033e-05,2.414e-05,1.4461e-05,9.4644e-06,4.8121e-06,4e-06,3e-06,2e-06,1e-06,7e-07,3.3e-07}
1573        root:myGlobals:Attenuators:ngAatt9 = {7e-05,2e-05,8.2796e-06,4.5619e-06,3.1543e-06,2.6216e-06,8e-07,6e-07,4e-07,3e-07,2e-07,1e-07,5e-08}
1574//      root:myGlobals:Attenuators:ngAatt10 = {}
1575
1576  // percent errors as measured, Jan 2013 values
1577  // zero error for zero attenuators, large values put in for unknown values (either 2% or 5%)
1578        root:myGlobals:Attenuators:ngAatt0_err = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
1579        root:myGlobals:Attenuators:ngAatt1_err = {0.12116,0.111059,0.150188,0.15168,0.174434,0.218745,0.0938678,0.144216,0.2145,0.141995,0.153655,0.157188,5}
1580        root:myGlobals:Attenuators:ngAatt2_err = {0.183583,0.19981,0.278392,0.286518,0.336599,0.240429,0.190996,0.178529,0.266807,0.23608,0.221334,0.245336,5}
1581        root:myGlobals:Attenuators:ngAatt3_err = {0.271054,0.326341,0.30164,0.31008,0.364188,0.296638,0.1914,0.22433,0.340313,0.307021,0.279339,0.319965,5}
1582        root:myGlobals:Attenuators:ngAatt4_err = {0.333888,0.361023,0.356208,0.368968,0.437084,0.322955,0.248284,0.260956,0.402069,0.368168,0.337252,0.454958,5}
1583        root:myGlobals:Attenuators:ngAatt5_err = {0.365745,0.433845,0.379735,0.394999,0.470603,0.357534,0.290938,0.291193,0.455465,0.426855,0.434639,2,5}
1584        root:myGlobals:Attenuators:ngAatt6_err = {0.402066,0.470239,0.410136,0.432342,0.523241,0.389247,0.333352,0.325301,0.517036,0.539386,2,2,5}
1585        root:myGlobals:Attenuators:ngAatt7_err = {0.542334,0.549954,0.45554,0.497426,0.624473,0.454971,0.432225,0.464043,0.752858,2,5,5,5}
1586        root:myGlobals:Attenuators:ngAatt8_err = {0.704775,0.673556,0.537178,0.62027,0.814375,0.582449,0.662811,2,2,5,5,5,5}
1587        root:myGlobals:Attenuators:ngAatt9_err = {2,2,0.583513,0.685477,0.901413,0.767115,2,5,5,5,5,5,5}
1588//      root:myGlobals:Attenuators:ngAatt10_err = {} 
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 3 and 30 (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 -- now correct, NGA table has been added, allowing for 3A to 30A
1701//
1702Function LookupAttenNGA(lambda,attenNo,atten_err)
1703        Variable lambda, attenNo, &atten_err
1704       
1705        Variable trans
1706        String attStr="root:myGlobals:Attenuators:ngAatt"+num2str(trunc(abs(attenNo)))
1707        String attErrWStr="root:myGlobals:Attenuators:ngAatt"+num2str(trunc(abs(attenNo)))+"_err"
1708        String lamStr = "root:myGlobals:Attenuators:ngAlambda"
1709       
1710        if(attenNo == 0)
1711                return (1)              //no attenuation, return trans == 1
1712        endif
1713       
1714        if( (lambda < 3) || (lambda > 30 ) )
1715                Abort "Wavelength out of calibration range (3,30). You must manually enter the absolute parameters"
1716        Endif
1717       
1718        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) || !(WaveExists($attErrWStr)))
1719                Execute "MakeNGAAttenTable()"
1720        Endif
1721        //just in case creating the tables fails....
1722        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) )
1723                Abort "Attenuator lookup waves could not be found. You must manually enter the absolute parameters"
1724        Endif
1725       
1726        //lookup the value by interpolating the wavelength
1727        //the attenuator must always be an integer
1728        Wave att = $attStr
1729        Wave attErrW = $attErrWStr
1730        Wave lam = $lamstr
1731        trans = interp(lambda,lam,att)
1732        atten_err = interp(lambda,lam,attErrW)
1733
1734// the error in the tables is % error. return the standard deviation instead
1735        atten_err = trans*atten_err/100
1736       
1737//      Print "trans = ",trans
1738//      Print "trans err = ",atten_err
1739       
1740        return trans
1741
1742End
1743
1744// a utility function so that I can get the values from the command line
1745// since the atten_err is PBR
1746//
1747Function PrintAttenuation(instr,lam,attenNo)
1748        String instr
1749        Variable lam,attenNo
1750       
1751        Variable atten_err, attenFactor
1752       
1753        strswitch(instr)
1754                case "NG3":
1755                        attenFactor = LookupAttenNG3(lam,attenNo,atten_err)
1756                        break
1757                case "NG5":
1758                        //using NG7 lookup Table
1759                        attenFactor = LookupAttenNG7(lam,attenNo,atten_err)
1760                        break
1761                case "NG7":
1762                        attenFactor = LookupAttenNG7(lam,attenNo,atten_err)
1763                        break
1764                case "NGA":
1765                        attenFactor = LookupAttenNGA(lam,attenNo,atten_err)
1766                        break
1767                default:                                                       
1768                        //return error?
1769                        DoAlert 0, "No matching instrument -- PrintAttenuation"
1770                        attenFactor=1
1771        endswitch
1772
1773        Print "atten, err = ", attenFactor, atten_err
1774       
1775        return(0)
1776End
1777
1778
1779
1780//returns the proper attenuation factor based on the instrument (NG3, NG5, or NG7)
1781//NG5 values are taken from the NG7 tables (there is very little difference in the
1782//values, and NG5 attenuators have not been calibrated (as of 8/01)
1783//
1784// filestr is passed from TextRead[3] = the default directory
1785// lam is passed from RealsRead[26]
1786// AttenNo is passed from ReaslRead[3]
1787//
1788// Attenuation factor as defined here is <= 1
1789//
1790// HFIR can pass ("",1,attenuationFactor) and have this function simply
1791// spit back the attenuationFactor (that was read into rw[3])
1792//
1793// called by Correct.ipf, ProtocolAsPanel.ipf, Transmission.ipf
1794//
1795//
1796// as of March 2011, returns the error (one standard deviation) in the attenuation factor as the last parameter, by reference
1797Function AttenuationFactor(fileStr,lam,attenNo,atten_err)
1798        String fileStr
1799        Variable lam,attenNo, &atten_err
1800       
1801        Variable attenFactor=1,loc
1802        String instr=fileStr[1,3]       //filestr is "[NGnSANSn] " or "[NGnSANSnn]" (11 characters total)
1803       
1804        strswitch(instr)
1805                case "NG3":
1806                        attenFactor = LookupAttenNG3(lam,attenNo,atten_err)
1807                        break
1808                case "NG5":
1809                        //using NG7 lookup Table
1810                        attenFactor = LookupAttenNG7(lam,attenNo,atten_err)
1811                        break
1812                case "NG7":
1813                        attenFactor = LookupAttenNG7(lam,attenNo,atten_err)
1814                        break
1815                case "NGA":
1816                        Print "Using the NG7 table for NGA *** this needs to be updated ***"
1817                        attenFactor = LookupAttenNGA(lam,attenNo,atten_err)
1818                        break
1819                default:                                                       
1820                        //return error?
1821                        DoAlert 0, "No matching instrument -- PrintAttenuation"
1822                        attenFactor=1
1823        endswitch
1824//      print "instr, lambda, attenNo,attenFactor = ",instr,lam,attenNo,attenFactor
1825        return(attenFactor)
1826End
1827
1828//function called by the popups to get a file list of data that can be sorted
1829// this procedure simply removes the raw data files from the string - there
1830//can be lots of other junk present, but this is very fast...
1831//
1832// could also use the alternate procedure of keeping only file with the proper extension
1833//
1834// another possibility is to get a listing of the text files, but is unreliable on
1835// Windows, where the data file must be .txt (and possibly OSX)
1836//
1837// called by FIT_Ops.ipf, NSORT.ipf, PlotUtils.ipf
1838//
1839Function/S ReducedDataFileList(ctrlName)
1840        String ctrlName
1841
1842        String list="",newList="",item=""
1843        Variable num,ii
1844       
1845        //check for the path
1846        PathInfo catPathName
1847        if(V_Flag==0)
1848                DoAlert 0, "Data path does not exist - pick the data path from the button on the main panel"
1849                Return("")
1850        Endif
1851       
1852        list = IndexedFile(catpathName,-1,"????")
1853       
1854        list = RemoveFromList(ListMatch(list,"*.SA1*",";"), list, ";", 0)
1855        list = RemoveFromList(ListMatch(list,"*.SA2*",";"), list, ";", 0)
1856        list = RemoveFromList(ListMatch(list,"*.SA3*",";"), list, ";", 0)
1857        list = RemoveFromList(ListMatch(list,"*.SA4*",";"), list, ";", 0)               // added JAN 2013 for new guide hall
1858        list = RemoveFromList(ListMatch(list,"*.SA5*",";"), list, ";", 0)
1859        list = RemoveFromList(ListMatch(list,".*",";"), list, ";", 0)
1860        list = RemoveFromList(ListMatch(list,"*.pxp",";"), list, ";", 0)
1861        list = RemoveFromList(ListMatch(list,"*.DIV",";"), list, ";", 0)
1862        list = RemoveFromList(ListMatch(list,"*.GSP",";"), list, ";", 0)
1863        list = RemoveFromList(ListMatch(list,"*.MASK",";"), list, ";", 0)
1864
1865        //remove VAX version numbers
1866        list = RemoveVersNumsFromList(List)
1867        //sort
1868        newList = SortList(List,";",0)
1869
1870        return newlist
1871End
1872
1873// returns a list of raw data files in the catPathName directory on disk
1874// - list is SEMICOLON-delimited
1875//
1876// does it the "cheap" way, simply finding the ".SAn" in the file name
1877// = does not check for proper byte length.
1878//
1879// called by PatchFiles.ipf, Tile_2D.ipf
1880//
1881Function/S GetRawDataFileList()
1882       
1883        //make sure that path exists
1884        PathInfo catPathName
1885        if (V_flag == 0)
1886                Abort "Folder path does not exist - use Pick Path button on Main Panel"
1887        Endif
1888       
1889        String list=IndexedFile(catPathName,-1,"????")
1890        String newList="",item=""
1891        Variable num=ItemsInList(list,";"),ii
1892        for(ii=0;ii<num;ii+=1)
1893                item = StringFromList(ii, list  ,";")
1894                if( stringmatch(item,"*.sa1*") )
1895                        newlist += item + ";"
1896                endif
1897                if( stringmatch(item,"*.sa2*") )
1898                        newlist += item + ";"
1899                endif
1900                if( stringmatch(item,"*.sa3*") )
1901                        newlist += item + ";"
1902                endif
1903                if( stringmatch(item,"*.sa4*") )                // added JAN 2013 for new guide hall
1904                        newlist += item + ";"
1905                endif
1906                if( stringmatch(item,"*.sa5*") )
1907                        newlist += item + ";"
1908                endif
1909                //print "ii=",ii
1910        endfor
1911        newList = SortList(newList,";",0)
1912        return(newList)
1913End
1914
1915// Return the filename that represents the previous or next file.
1916// Input is current filename and increment.
1917// Increment should be -1 or 1
1918// -1 => previous file
1919// 1 => next file
1920Function/S GetPrevNextRawFile(curfilename, prevnext)
1921        String curfilename
1922        Variable prevnext
1923
1924        String filename
1925       
1926        //get the run number
1927        Variable num = GetRunNumFromFile(curfilename)
1928               
1929        //find the next specified file by number
1930        fileName = FindFileFromRunNumber(num+prevnext)
1931
1932        if(cmpstr(fileName,"")==0)
1933                //null return, do nothing
1934                fileName = FindFileFromRunNumber(num)
1935        Endif
1936
1937//      print "in FU "+filename
1938
1939        Return filename
1940End
1941
1942
Note: See TracBrowser for help on using the repository browser.