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

Last change on this file since 1217 was 1217, checked in by srkline, 3 years ago

fixed minor bugs in attenuator table definition (didn't affect calculations), VCALC display, and sector averaging of the back detector on VSANS

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