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

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

Lots of changes:
-2D resolution smearing
-2D error propagation

1) 2D resolution smearing has been corrected to use sigma (perp) correctly
rather than phi. This shows up in the quadrature loop in all of the 2D models
and in the Smear_2D "generic" function.

2) 1D resolutionn smearing is now corrected to account for the integration
range of +/- 3 sigma (99.73% of distribution). Now the result is divided by
0.9973 to rescale it to the correct value.

3) Smeared models are now AAO to improve speed and to allow easier use with
functions that are inherently AAO. No changes are needed, since the call is
behind the scenes, replacing Smear_Model_N() with Smear_Model_N_AAO().

4) in PlotUtils_2D added functions to re-bin the QxQy? data into a 1D format
BinQxQy_to_1D(). This also re-bins the errors in two ways, adding the per-pixel
errors in quadrature, or the deviation from the mean of the intensity. Manually
editing the intensity declaration allows 2D->1D binning of smeared models.

5) Per-pixel propagation of errors has been added through the entire data
reduction sequence. Data errors are generated on loading using Poisson
statistics (specifically tailored for accuracy at low counts) and then is
propagated through each manipulation of the data using standard error
propagation. The error matrix is linear_data_error. As a by-product, all of
the math operations on data are explicitly done on linear_data, to avoid
any potential mistakes of log/linear scaling. Results of this propagation
largely match J. Barker's /ERROR routines from the VAX, with some differences
at low data count values (as expected) and at higher count values near the
beam stop (somewhat unexpected). This per-pixel error is ouput in the QxQy_ASCII
data files. NO CHANGE has been made to the 1D data, which uses the deviation from
the mean as the error - since this is correct.

6) Added tables for the uncertainty in attenuator transmission (from JGB)

7) added two more REAL values to the VAX header to store information
necessary for error propagation. These are couting error that are part of
the transmission error and of the absolute scaling error. These add Read/Write?
functions in NCNR_DataReadWrite

The transmission error (one standard deviation) is written at byte 396 (4 bytes)

RealsRead?[41]

The Box Sum error (one standard deviation) is written at byte 400 (4 bytes)

RealsRead?[42]

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