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

Last change on this file since 838 was 838, checked in by srkline, 11 years ago

adding two new help files for real space modeling and description of the 2D resolution function

cleaning up the FFT routines for addition as a beta operation

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