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

Last change on this file since 788 was 788, checked in by srkline, 12 years ago

Added patch to use the correct detector dead time based on whether VAX or ICE hardware was used. The switch is done based on the day of data acquisition using dates supplied by Jeff and Cedric for the date past which the VAX hardware was not used.

25-FEB-2010 for NG7
23-JUL-2009 for NG3

Any data collected after these dates will use the measured dead time with ICE hardware.

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