source: sans/SANSReduction/trunk/Put in User Procedures/SANS_Reduction_v5.00/NCNR_Utils.ipf @ 118

Last change on this file since 118 was 118, checked in by srkline, 15 years ago

Updated attenuator tables have been added for NG7 only. NG3 has yet to be measured (JGB). This new calibration is nearly identical to the old table. The new table has also been extrapolated to 4A and to 20A to cover odd situations.

File size: 37.0 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma version=5.0
3#pragma IgorVersion=5.0
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        Variable/G root:myGlobals:PixelResNG3_ILL = 1.0         //pixel resolution in cm
27        Variable/G root:myGlobals:PixelResNG5_ILL = 1.0
28        Variable/G root:myGlobals:PixelResNG7_ILL = 1.0
29        Variable/G root:myGlobals:PixelResNG3_ORNL = 0.5
30        Variable/G root:myGlobals:PixelResNG5_ORNL = 0.5
31        Variable/G root:myGlobals:PixelResNG7_ORNL = 0.5
32        Variable/G root:myGlobals:PixelResDefault = 0.5
33       
34        Variable/G root:myGlobals:DeadtimeNG3_ILL = 3.0e-6              //deadtime in seconds
35        Variable/G root:myGlobals:DeadtimeNG5_ILL = 3.0e-6
36        Variable/G root:myGlobals:DeadtimeNG7_ILL = 3.0e-6
37        Variable/G root:myGlobals:DeadtimeNG3_ORNL = 3.4e-6
38        Variable/G root:myGlobals:DeadtimeNG5_ORNL = 0.6e-6             //as of 9 MAY 2002
39        Variable/G root:myGlobals:DeadtimeNG7_ORNL = 3.4e-6
40        Variable/G root:myGlobals:DeadtimeDefault = 3.4e-6
41       
42        //new 11APR07
43        Variable/G root:myGlobals:BeamstopXTol = -5                     // (cm) is BS Xpos is -5 cm or less, it's a trans measurement
44        // sample aperture offset is NOT stored in the VAX header, but it should be
45        // - when it is, remove the global and write an accessor AND make a place for
46        // it in the RealsRead
47        Variable/G root:myGlobals:apOff = 5.0                           // (cm) distance from sample aperture to sample position
48
49End
50
51
52//**********************
53// Resolution calculation - used by the averaging routines
54// to calculate the resolution function at each q-value
55// - the return value is not used
56//
57// equivalent to John's routine on the VAX Q_SIGMA_AVE.FOR
58// Incorporates eqn. 3-15 from J. Appl. Cryst. (1995) v. 28 p105-114
59//
60// - 21 MAR 07 uses projected BS diameter on the detector
61// - APR 07 still need to add resolution with lenses. currently there is no flag in the
62//          raw data header to indicate the presence of lenses.
63//
64// - called by CircSectAvg.ipf and RectAnnulAvg.ipf
65//
66// passed values are read from RealsRead
67// except DDet and apOff, which are set from globals before passing
68//
69Function/S getResolution(inQ,lambda,lambdaWidth,DDet,apOff,S1,S2,L1,L2,BS,del_r,SigmaQ,QBar,fSubS)
70        Variable inQ, lambda, lambdaWidth, DDet, apOff, S1, S2, L1, L2, BS, del_r
71        Variable &fSubS, &QBar, &SigmaQ         //these are the output quantities at the input Q value
72       
73        //lots of calculation variables
74        Variable a2, q_small, lp, v_lambda, v_b, v_d, vz, yg, v_g
75        Variable r0, delta, inc_gamma, fr, fv, rmd, v_r1, rm, v_r
76
77        //Constants
78        Variable vz_1 = 3.956e5         //velocity [cm/s] of 1 A neutron
79        Variable g = 981.0                              //gravity acceleration [cm/s^2]
80
81        String results
82        results ="Failure"
83
84        S1 *= 0.5*0.1                   //convert to radius and [cm]
85        S2 *= 0.5*0.1
86
87        L1 *= 100.0                     // [cm]
88        L1 -= apOff                             //correct the distance
89
90        L2 *= 100.0
91        L2 += apOff
92        del_r *= 0.1                            //width of annulus, convert mm to [cm]
93       
94        BS *= 0.5*0.1                   //nominal BS diameter passed in, convert to radius and [cm]
95        // 21 MAR 07 SRK - use the projected BS diameter, based on a point sample aperture
96        Variable LB
97        LB = 20.1 + 1.61*BS                     //distance in cm from beamstop to anode plane (empirical)
98        BS = bs + bs*lb/(l2-lb)         //adjusted diameter of shadow from parallax
99       
100        //Start resolution calculation
101        a2 = S1*L2/L1 + S2*(L1+L2)/L1
102        q_small = 2.0*Pi*(BS-a2)*(1.0-lambdaWidth)/(lambda*L2)
103        lp = 1.0/( 1.0/L1 + 1.0/L2)
104
105        v_lambda = lambdaWidth^2/6.0
106        v_b = 0.25*(S1*L2/L1)^2 +0.25*(S2*L2/lp)^2
107        v_d = (DDet/2.3548)^2 + del_r^2/12.0
108        vz = vz_1 / lambda
109        yg = 0.5*g*L2*(L1+L2)/vz^2
110        v_g = 2.0*yg^2*v_lambda
111
112        r0 = L2*tan(2.0*asin(lambda*inQ/(4.0*Pi) ))
113        delta = 0.5*(BS - r0)^2/v_d
114
115        if (r0 < BS)
116                inc_gamma=exp(gammln(1.5))*(1-gammp(1.5,delta))
117        else
118                inc_gamma=exp(gammln(1.5))*(1+gammp(1.5,delta))
119        endif
120
121        fSubS = 0.5*(1.0+erf( (r0-BS)/sqrt(2.0*v_d) ) )
122        if (fSubS <= 0.0)
123                fSubS = 1.e-10
124        endif
125        fr = 1.0 + sqrt(v_d)*exp(-1.0*delta) /(r0*fSubS*sqrt(2.0*Pi))
126        fv = inc_gamma/(fSubS*sqrt(Pi)) - r0^2*(fr-1.0)^2/v_d
127
128        rmd = fr*r0
129        v_r1 = v_b + fv*v_d +v_g
130
131        rm = rmd + 0.5*v_r1/rmd
132        v_r = v_r1 - 0.5*(v_r1/rmd)^2
133        if (v_r < 0.0)
134                v_r = 0.0
135        endif
136        QBar = (4.0*Pi/lambda)*sin(0.5*atan(rm/L2))
137        SigmaQ = QBar*sqrt(v_r/rmd^2 +v_lambda)
138
139        results = "success"
140        Return results
141End
142
143
144//Utility function that returns the detector resolution (in cm)
145//Global values are set in the Initialize procedure
146//
147//
148// - called by CircSectAvg.ipf, RectAnnulAvg.ipf, and ProtocolAsPanel.ipf
149//
150// fileStr is passed as TextRead[3]
151// detStr is passed as TextRead[9]
152//
153Function DetectorPixelResolution(fileStr,detStr)
154        String fileStr,detStr
155       
156        Variable DDet
157        String instr=fileStr[1,3]       //filestr is "[NGnSANSn] " or "[NGnSANSnn]" (11 characters total)
158       
159        NVAR PixelResNG3_ILL = root:myGlobals:PixelResNG3_ILL           //pixel resolution in cm
160        NVAR PixelResNG5_ILL = root:myGlobals:PixelResNG5_ILL
161        NVAR PixelResNG7_ILL = root:myGlobals:PixelResNG7_ILL
162        NVAR PixelResNG3_ORNL = root:myGlobals:PixelResNG3_ORNL
163        NVAR PixelResNG5_ORNL = root:myGlobals:PixelResNG5_ORNL
164        NVAR PixelResNG7_ORNL = root:myGlobals:PixelResNG7_ORNL
165        NVAR PixelResDefault = root:myGlobals:PixelResDefault
166       
167        strswitch(instr)
168                case "NG3":
169                        if(cmpstr(detStr, "ILL   ") == 0 )
170                                DDet= PixelResNG3_ILL
171                        else
172                                DDet = PixelResNG3_ORNL //detector is ordella-type
173                        endif
174                        break
175                case "NG5":
176                        if(cmpstr(detStr, "ILL   ") == 0 )
177                                DDet= PixelResNG5_ILL
178                        else
179                                DDet = PixelResNG5_ORNL //detector is ordella-type
180                        endif
181                        break
182                case "NG7":
183                        if(cmpstr(detStr, "ILL   ") == 0 )
184                                DDet= PixelResNG7_ILL
185                        else
186                                DDet = PixelResNG7_ORNL //detector is ordella-type
187                        endif
188                        break
189                default:                                                       
190                        //return error?
191                        DDet = PixelResDefault  //0.5 cm, typical for new ORNL detectors
192        endswitch
193       
194        return(DDet)
195End
196
197//Utility function that returns the detector deadtime (in seconds)
198//Global values are set in the Initialize procedure
199//
200// - called by WorkFileUtils.ipf
201//
202// fileStr is passed as TextRead[3]
203// detStr is passed as TextRead[9]
204//
205Function DetectorDeadtime(fileStr,detStr)
206        String fileStr,detStr
207       
208        Variable deadtime
209        String instr=fileStr[1,3]       //filestr is "[NGnSANSn] " or "[NGnSANSnn]" (11 characters total)
210       
211        NVAR DeadtimeNG3_ILL = root:myGlobals:DeadtimeNG3_ILL           //pixel resolution in cm
212        NVAR DeadtimeNG5_ILL = root:myGlobals:DeadtimeNG5_ILL
213        NVAR DeadtimeNG7_ILL = root:myGlobals:DeadtimeNG7_ILL
214        NVAR DeadtimeNG3_ORNL = root:myGlobals:DeadtimeNG3_ORNL
215        NVAR DeadtimeNG5_ORNL = root:myGlobals:DeadtimeNG5_ORNL
216        NVAR DeadtimeNG7_ORNL = root:myGlobals:DeadtimeNG7_ORNL
217        NVAR DeadtimeDefault = root:myGlobals:DeadtimeDefault
218       
219        strswitch(instr)
220                case "NG3":
221                        if(cmpstr(detStr, "ILL   ") == 0 )
222                                deadtime= DeadtimeNG3_ILL
223                        else
224                                deadtime = DeadtimeNG3_ORNL     //detector is ordella-type
225                        endif
226                        break
227                case "NG5":
228                        if(cmpstr(detStr, "ILL   ") == 0 )
229                                deadtime= DeadtimeNG5_ILL
230                        else
231                                deadtime = DeadtimeNG5_ORNL     //detector is ordella-type
232                        endif
233                        break
234                case "NG7":
235                        if(cmpstr(detStr, "ILL   ") == 0 )
236                                deadtime= DeadtimeNG7_ILL
237                        else
238                                deadtime = DeadtimeNG7_ORNL     //detector is ordella-type
239                        endif
240                        break
241                default:                                                       
242                        //return error?
243                        deadtime = DeadtimeDefault      //1e-6 seconds, typical for new ORNL detectors
244        endswitch
245       
246        return(deadtime)
247End
248
249
250/////VAX filename/Run number parsing utilities
251//
252// a collection of uilities for processing vax filenames
253//and processing lists (especially for display in popup menus)
254//
255//required to correctly account for VAX supplied version numbers, which
256//may or may not be removed by the ftp utility
257//
258// - parses lists of run numbers into real filenames
259// - selects proper detector constants
260//
261//**************************
262//
263//given a filename of a SANS data filename of the form
264//TTTTTnnn.SAn_TTT_Txxx
265//returns the run number "nnn" as a number
266//returns -1 as an invalid file number
267//
268// called by several ipfs
269//
270//
271Function GetRunNumFromFile(item)
272        String item
273        Variable invalid = -1   //negative numbers are invalid
274        Variable num=-1
275       
276        //find the "dot"
277        String runStr=""
278        Variable pos = strsearch(item,".",0)
279        if(pos == -1)
280                //"dot" not found
281                return (invalid)
282        else
283                //found, get the three characters preceeding it
284                if (pos <=2)
285                        //not enough characters
286                        return (invalid)
287                else
288                        runStr = item[pos-3,pos-1]
289                        //convert to a number
290                        num = str2num(runStr)
291                        //if valid, return it
292                        if (num == NaN)
293                                //3 characters were not a number
294                                return (invalid)
295                        else
296                                //run was OK
297                                return (num)
298                        Endif
299                Endif
300        Endif
301End
302
303//given a filename of a SANS data filename of the form
304//TTTTTnnn.SAn_TTT_Txxx
305//returns the run number "nnn" as a STRING of THREE characters
306//returns "ABC" as an invalid file number
307//
308// local function to aid in locating files by run number
309//
310Function/S GetRunNumStrFromFile(item)
311        String item
312        String invalid = "ABC"  //"ABC" is not a valid run number, since it's text
313        Variable num=-1
314       
315        //find the "dot"
316        String runStr=""
317        Variable pos = strsearch(item,".",0)
318        if(pos == -1)
319                //"dot" not found
320                return (invalid)
321        else
322                //found, get the three characters preceeding it
323                if (pos <=2)
324                        //not enough characters
325                        return (invalid)
326                else
327                        runStr = item[pos-3,pos-1]
328                        return (runStr)
329                Endif
330        Endif
331End
332
333//returns a string containing the full path to the file containing the
334//run number "num". The null string is returned if no valid file can be found
335//the path "catPathName" used and is hard-wired, will abort if this path does not exist
336//the file returned will be a RAW SANS data file, other types of files are
337//filtered out.
338//
339// called by Buttons.ipf and Transmission.ipf, and locally by parsing routines
340//
341Function/S FindFileFromRunNumber(num)
342        Variable num
343       
344        String fullName="",partialName="",item=""
345        //get list of raw data files in folder that match "num" (add leading zeros)
346        if( (num>999) || (num<=0) )
347                //Print "error in  FindFileFromRunNumber(num), file number too large or too small"
348                Return ("")
349        Endif
350        //make a three character string of the run number
351        String numStr=""
352        if(num<10)
353                numStr = "00"+num2str(num)
354        else
355                if(num<100)
356                        numStr = "0"+num2str(num)
357                else
358                        numStr = num2str(num)
359                Endif
360        Endif
361        //Print "numstr = ",numstr
362       
363        //make sure that path exists
364        PathInfo catPathName
365        String path = S_path
366        if (V_flag == 0)
367                Abort "folder path does not exist - use Pick Path button"
368        Endif
369        String list="",newList="",testStr=""
370       
371        list = IndexedFile(catPathName,-1,"????")       //get all files in folder
372        //find (the) one with the number in the run # location in the name
373        Variable numItems,ii,runFound,isRAW
374        numItems = ItemsInList(list,";")                //get the new number of items in the list
375        ii=0
376        do
377                //parse through the list in this order:
378                // 1 - does item contain run number (as a string) "TTTTTnnn.SAn_XXX_Tyyy"
379                // 2 - exclude by isRaw? (to minimize disk access)
380                item = StringFromList(ii, list  ,";" )
381                if(strlen(item) != 0)
382                        //find the run number, if it exists as a three character string
383                        testStr = GetRunNumStrFromFile(item)
384                        runFound= cmpstr(numStr,testStr)        //compare the three character strings, 0 if equal
385                        if(runFound == 0)
386                                //the run Number was found
387                                //build valid filename
388                                partialName = FindValidFileName(item)
389                                if(strlen(partialName) != 0)            //non-null return from FindValidFileName()
390                                        fullName = path + partialName
391                                        //check if RAW, if so,this must be the file!
392                                        isRAW = CheckIfRawData(fullName)
393                                        if(isRaw)
394                                                //stop here
395                                                return(fullname)
396                                        Endif
397                                Endif
398                        Endif
399                Endif
400                ii+=1
401        while(ii<numItems)              //process all items in list
402        Return ("")     //null return if file not found in list
403End
404
405//function to test a binary file to see if it is a RAW binary SANS file
406//first checks the total bytes in the file (which for raw data is 33316 bytes)
407//**note that the "DIV" file will also show up as a raw file by the run field
408//should be listed in CAT/SHORT and in patch windows
409//
410//Function then checks the file fname (full path:file) for "RAW" run.type field
411//if not found, the data is not raw data and zero is returned
412//
413// called by many procedures (both external and local)
414//
415Function CheckIfRawData(fname)
416        String fname
417       
418        Variable refnum,totalBytes
419        String testStr=""
420       
421        Open/R/T="????TEXT" refNum as fname
422        //get the total number of bytes in the file
423        FStatus refNum
424        totalBytes = V_logEOF
425        //Print totalBytes
426        FSetPos refNum,75
427        FReadLine/N=3 refNum,testStr
428        Close refNum
429       
430        if(totalBytes == 33316 && cmpstr(testStr,"RAW")==0)
431                //true, is raw data file
432                Return(1)
433        else
434                //some other file
435                Return(0)
436        Endif
437End
438
439//function to check the header of a raw data file (full path specified by fname)
440//checks the field of the x-position of the beamstop during data collection
441//if the x-position is more negative (farther to the left) than xTol(input)
442//the the beamstop is "out" and the file is a transmission run and not a scattering run
443//xtol typically set at -5 (cm) - trans runs have bs(x) at -10 to -15 cm
444// function returns 1 if beamstop is out, 0 if beamstop is in
445//
446// tolerance is set as a global value "root:myGlobals:BeamstopXTol"
447//
448// called by Transmission.ipf, CatVSTable.ipf, NSORT.ipf
449//
450Function isTransFile(fName)
451        String fname
452       
453        Variable refnum,xpos
454        NVAR xTol = root:myGlobals:BeamstopXTol
455       
456        //pos = 369, read one real value
457       
458        SetDataFolder root:
459        String GBLoadStr="GBLoadWave/O/N=tempGBwave/T={2,2}/J=2/W=1/Q"
460        String strToExecute=""
461        // 1 R*4 value
462        strToExecute = GBLoadStr + "/S=368/U=1" + "\"" + fname + "\""
463        Execute strToExecute
464        Wave w=$"root:tempGBWave0"
465        xPos = w[0]
466        KillWaves/Z w
467        //Print "xPos = ",xpos
468       
469        if(xpos<=xTol)
470                //xpos is farther left (more negative) than xtol (currently -5 cm)
471                Return(1)
472        else
473                //some other file
474                Return(0)
475        Endif
476End
477
478
479//function to remove all spaces from names when searching for filenames
480//the filename (as saved) will never have interior spaces (TTTTTnnn_AB _Bnnn)
481//but the text field in the header WILL, if less than 3 characters were used for the
482//user's initials, and can have leading spaces if prefix was less than 5 characters
483//
484//returns a string identical to the original string, except with the interior spaces removed
485//
486// local function for file name manipulation
487//
488Function/S RemoveAllSpaces(str)
489        String str
490       
491        String tempstr = str
492        Variable ii,spc,len             //should never be more than 2 or 3 trailing spaces in a filename
493        ii=0
494        do
495                len = strlen(tempStr)
496                spc = strsearch(tempStr," ",0)          //is the last character a space?
497                if (spc == -1)
498                        break           //no more spaces found, get out
499                endif
500                str = tempstr
501                tempStr = str[0,(spc-1)] + str[(spc+1),(len-1)] //remove the space from the string
502        While(1)        //should never be more than 2 or 3
503       
504        If(strlen(tempStr) < 1)
505                tempStr = ""            //be sure to return a null string if problem found
506        Endif
507       
508        //Print strlen(tempstr)
509       
510        Return(tempStr)
511               
512End
513
514
515//Function attempts to find valid filename from partial name by checking for
516// the existence of the file on disk.
517// - checks as is
518// - adds ";vers" for possible VAX files
519// - strips spaces
520// - permutations of upper/lowercase
521//
522// added 11/99 - uppercase and lowercase versions of the file are tried, if necessary
523// since from marquee, the filename field (textread[0]) must be used, and can be a mix of
524// upper/lowercase letters, while the filename on the server (should) be all caps
525// now makes repeated calls to ValidFileString()
526//
527// returns a valid filename (No path prepended) or a null string
528//
529// called by any functions, both external and local
530//
531Function/S FindValidFilename(partialName)
532        String PartialName
533       
534        String retStr=""
535       
536        //try name with no changes - to allow for ABS files that have spaces in the names 12APR04
537        retStr = ValidFileString(partialName)
538        if(cmpstr(retStr,"") !=0)
539                //non-null return
540                return(retStr)
541        Endif
542       
543        //if the partial name is derived from the file header, there can be spaces at the beginning
544        //or in the middle of the filename - depending on the prefix and initials used
545        //
546        //remove any leading spaces from the name before starting
547        partialName = RemoveAllSpaces(partialName)
548       
549        //try name with no spaces
550        retStr = ValidFileString(partialName)
551        if(cmpstr(retStr,"") !=0)
552                //non-null return
553                return(retStr)
554        Endif
555       
556        //try all UPPERCASE
557        partialName = UpperStr(partialName)
558        retStr = ValidFileString(partialName)
559        if(cmpstr(retStr,"") !=0)
560                //non-null return
561                return(retStr)
562        Endif
563       
564        //try all lowercase (ret null if failure)
565        partialName = LowerStr(partialName)
566        retStr = ValidFileString(partialName)
567        if(cmpstr(retStr,"") !=0)
568                //non-null return
569                return(retStr)
570        else
571                return(retStr)
572        Endif
573End
574
575// Function checks for the existence of a file
576// partialName;vers (to account for VAX filenaming conventions)
577// The partial name is tried first with no version number
578//
579// *** the PATH is hard-wired to catPathName (which is assumed to exist)
580// version numers up to ;10 are tried
581// only the "name;vers" is returned if successful. The path is not prepended
582//
583// local function
584//
585Function/S ValidFileString(partialName)
586        String partialName
587       
588        String tempName = "",msg=""
589        Variable ii,refnum
590       
591        ii=0
592        do
593                if(ii==0)
594                        //first pass, try the partialName
595                        tempName = partialName
596                        Open/Z/R/T="????TEXT"/P=catPathName refnum tempName     //Does open file (/Z flag)
597                        if(V_flag == 0)
598                                //file exists
599                                Close refnum            //YES needed,
600                                break
601                        endif
602                else
603                        tempName = partialName + ";" + num2str(ii)
604                        Open/Z/R/T="????TEXT"/P=catPathName refnum tempName
605                        if(V_flag == 0)
606                                //file exists
607                                Close refnum
608                                break
609                        endif
610                Endif
611                ii+=1
612                //print "ii=",ii
613        while(ii<11)
614        //go get the selected bits of information, using tempName, which exists
615        if(ii>=11)
616                //msg = partialName + " not found. is version number > 11?"
617                //DoAlert 0, msg
618                //PathInfo catPathName
619                //Print S_Path
620                Return ("")             //use null string as error condition
621        Endif
622       
623        Return (tempName)
624End
625
626//returns a string containing filename (WITHOUT the ;vers)
627//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
628//with the folders separated by colons
629//
630// called by MaskUtils.ipf, ProtocolAsPanel.ipf, WriteQIS.ipf
631//
632Function/S GetFileNameFromPathNoSemi(fullPath)
633        String fullPath
634       
635        Variable offset1,offset2
636        String filename=""
637        //String PartialPath
638        offset1 = 0
639        do
640                offset2 = StrSearch(fullPath, ":", offset1)
641                if (offset2 == -1)                              // no more colons ?
642                        fileName = FullPath[offset1,strlen(FullPath) ]
643                        //PartialPath = FullPath[0, offset1-1]
644                        break
645                endif
646                offset1 = offset2+1
647        while (1)
648       
649        //remove version number from name, if it's there - format should be: filename;N
650        filename =  StringFromList(0,filename,";")              //returns null if error
651       
652        Return filename
653End
654
655//returns a string containing filename (INCLUDING the ;vers)
656//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
657//with the folders separated by colons
658//
659// local, currently unused
660//
661Function/S GetFileNameFromPathKeepSemi(fullPath)
662        String fullPath
663       
664        Variable offset1,offset2
665        String filename
666        //String PartialPath
667        offset1 = 0
668        do
669                offset2 = StrSearch(fullPath, ":", offset1)
670                if (offset2 == -1)                              // no more colons ?
671                        fileName = FullPath[offset1,strlen(FullPath) ]
672                        //PartialPath = FullPath[0, offset1-1]
673                        break
674                endif
675                offset1 = offset2+1
676        while (1)
677       
678        //keep version number from name, if it's there - format should be: filename;N
679       
680        Return filename
681End
682
683//given the full path and filename (fullPath), strips the data path
684//(Mac-style, separated by colons) and returns this path
685//this partial path is the same string that would be returned from PathInfo, for example
686//
687// - allows the user to save to a different path than catPathName
688//
689// called by WriteQIS.ipf
690//
691Function/S GetPathStrFromfullName(fullPath)
692        String fullPath
693       
694        Variable offset1,offset2
695        //String filename
696        String PartialPath
697        offset1 = 0
698        do
699                offset2 = StrSearch(fullPath, ":", offset1)
700                if (offset2 == -1)                              // no more colons ?
701                        //fileName = FullPath[offset1,strlen(FullPath) ]
702                        PartialPath = FullPath[0, offset1-1]
703                        break
704                endif
705                offset1 = offset2+1
706        while (1)
707       
708        Return PartialPath
709End
710
711//given the VAX filename, pull off the first 8 characters to make a valid
712//file string that can be used for naming averaged 1-d files
713//
714// called by ProtocolAsPanel.ipf and Tile_2D.ipf
715//
716Function/S GetNameFromHeader(fullName)
717        String fullName
718        String temp, newName = ""
719        Variable spc,ii=0
720       
721        //filename is 20 characters NNNNNxxx.SAn_NNN_NNN
722        //want the first 8 characters, NNNNNxxx, then strip off any spaces at the beginning
723        //NNNNN was entered as less than 5 characters
724        //returns a null string if no name can be found
725        do
726                temp = fullname[ii,7]           //characters ii,7 of the name
727                spc = strsearch(temp," ",0)
728                if (spc == -1)
729                        break           //no more spaces found
730                endif
731                ii+=1
732        While(ii<8)
733       
734        If(strlen(temp) < 1)
735                newName = ""            //be sure to return a null string if problem found
736        else
737                newName = temp
738        Endif
739       
740        Return(newName)
741End
742
743//list (input) is a list, typically returned from IndexedFile()
744//which is semicolon-delimited, and may contain filenames from the VAX
745//that contain version numbers, where the version number appears as a separate list item
746//(and also as a non-existent file)
747//these numbers must be purged from the list, especially for display in a popup
748//or list processing of filenames
749//the function returns the list, cleaned of version numbers (up to 11)
750//raw data files will typically never have a version number other than 1.
751//
752// if there are no version numbers in the list, the input list is returned
753//
754// called by CatVSTable.ipf, NSORT.ipf, Transmission.ipf, WorkFileUtils.ipf
755//
756Function/S RemoveVersNumsFromList(list)
757        String list
758       
759        //get rid of version numbers first (up to 11)
760        Variable ii,num
761        String item
762        num = ItemsInList(list,";")
763        ii=1
764        do
765                item = num2str(ii)
766                list = RemoveFromList(item, list ,";" )
767                ii+=1
768        while(ii<12)
769       
770        return (list)
771End
772
773//input is a list of run numbers, and output is a list of filenames (not the full path)
774//*** input list must be COMMA delimited***
775//output is equivalent to selecting from the CAT table
776//if some or all of the list items are valid filenames, keep them...
777//if an error is encountered, notify of the offending element and return a null list
778//
779//output is COMMA delimited
780//
781// this routine is expecting that the "ask", "none" special cases are handled elsewhere
782//and not passed here
783//
784// called by Marquee.ipf, MultipleReduce.ipf, ProtocolAsPanel.ipf
785//
786Function/S ParseRunNumberList(list)
787        String list
788       
789        String newList="",item="",tempStr=""
790        Variable num,ii,runNum
791       
792        //expand number ranges, if any
793        list = ExpandNumRanges(list)
794       
795        num=itemsinlist(list,",")
796       
797        for(ii=0;ii<num;ii+=1)
798                //get the item
799                item = StringFromList(ii,list,",")
800                //is it already a valid filename?
801                tempStr=FindValidFilename(item) //returns filename if good, null if error
802                if(strlen(tempstr)!=0)
803                        //valid name, add to list
804                        //Print "it's a file"
805                        newList += tempStr + ","
806                else
807                        //not a valid name
808                        //is it a number?
809                        runNum=str2num(item)
810                        //print runnum
811                        if(numtype(runNum) != 0)
812                                //not a number -  maybe an error                       
813                                DoAlert 0,"List item "+item+" is not a valid run number or filename. Please enter a valid number or filename."
814                                return("")
815                        else
816                                //a run number or an error
817                                tempStr = GetFileNameFromPathNoSemi( FindFileFromRunNumber(runNum) )
818                                if(strlen(tempstr)==0)
819                                        //file not found, error
820                                        DoAlert 0,"List item "+item+" is not a valid run number. Please enter a valid number."
821                                        return("")
822                                else
823                                        newList += tempStr + ","
824                                endif
825                        endif
826                endif
827        endfor          //loop over all items in list
828       
829        return(newList)
830End
831
832//takes a comma delimited list that MAY contain number range, and
833//expands any range of run numbers into a comma-delimited list...
834//and returns the new list - if not a range, return unchanged
835//
836// local function
837//
838Function/S ExpandNumRanges(list)
839        String list
840       
841        String newList="",dash="-",item,str
842        Variable num,ii,hasDash
843       
844        num=itemsinlist(list,",")
845//      print num
846        for(ii=0;ii<num;ii+=1)
847                //get the item
848                item = StringFromList(ii,list,",")
849                //does it contain a dash?
850                hasDash = strsearch(item,dash,0)                //-1 if no dash found
851                if(hasDash == -1)
852                        //not a range, keep it in the list
853                        newList += item + ","
854                else
855                        //has a dash (so it's a range), expand (or add null)
856                        newList += ListFromDash(item)           
857                endif
858        endfor
859       
860        return newList
861End
862
863//be sure to add a trailing comma to the return string...
864//
865// local function
866//
867Function/S ListFromDash(item)
868        String item
869       
870        String numList="",loStr="",hiStr=""
871        Variable lo,hi,ii
872       
873        loStr=StringFromList(0,item,"-")        //treat the range as a list
874        hiStr=StringFromList(1,item,"-")
875        lo=str2num(loStr)
876        hi=str2num(hiStr)
877        if( (numtype(lo) != 0) || (numtype(hi) !=0 ) || (lo > hi) )
878                numList=""
879                return numList
880        endif
881        for(ii=lo;ii<=hi;ii+=1)
882                numList += num2str(ii) + ","
883        endfor
884       
885        Return numList
886End
887
888
889////////Transmission
890//******************
891//lookup tables for attenuator transmissions
892//NG3 and NG7 attenuators are physically different, so the transmissions are slightly different
893//NG1 - (8m SANS) is not supported
894//
895// local function
896//
897Proc MakeNG3AttenTable()
898
899        NewDataFolder/O root:myGlobals:Attenuators
900        //do explicitly to avoid data folder problems, redundant, but it must work without fail
901        Make/O/N=9 root:myGlobals:Attenuators:ng3att0
902        Make/O/N=9 root:myGlobals:Attenuators:ng3att1
903        Make/O/N=9 root:myGlobals:Attenuators:ng3att2
904        Make/O/N=9 root:myGlobals:Attenuators:ng3att3
905        Make/O/N=9 root:myGlobals:Attenuators:ng3att4
906        Make/O/N=9 root:myGlobals:Attenuators:ng3att5
907        Make/O/N=9 root:myGlobals:Attenuators:ng3att6
908        Make/O/N=9 root:myGlobals:Attenuators:ng3att7
909        Make/O/N=9 root:myGlobals:Attenuators:ng3att8
910        Make/O/N=9 root:myGlobals:Attenuators:ng3att9
911        Make/O/N=9 root:myGlobals:Attenuators:ng3att10
912       
913        //each wave has 8 elements, the transmission of att# at the wavelengths
914        //lambda = 5,6,7,8,10,12,14,17
915        Make/O/N=9 root:myGlobals:Attenuators:ng3lambda={5,6,7,8,10,12,14,17,20}
916        root:myGlobals:Attenuators:ng3att0 = {1, 1, 1, 1, 1, 1, 1, 1,1 }
917        root:myGlobals:Attenuators:ng3att1 = {0.421, 0.394, 0.371, 0.349, 0.316, 0.293, 0.274, 0.245,0.220}
918        root:myGlobals:Attenuators:ng3att2 = {0.187, 0.164, 0.145, 0.130, 0.106, 0.0916, 0.0808, 0.0651,0.0531}
919        root:myGlobals:Attenuators:ng3att3 = {0.0777, 0.0636, 0.0534, 0.0446, 0.0330, 0.0262, 0.0217, 0.0157 ,0.0116}
920        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}
921        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}
922        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}
923        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}
924        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}
925        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}
926        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}
927
928End
929
930Proc MakeNG7AttenTable()
931
932        NewDataFolder/O root:myGlobals:Attenuators
933        Variable num=10
934        Make/O/N=(num) root:myGlobals:Attenuators:ng7att0
935        Make/O/N=(num) root:myGlobals:Attenuators:ng7att1
936        Make/O/N=(num) root:myGlobals:Attenuators:ng7att2
937        Make/O/N=(num) root:myGlobals:Attenuators:ng7att3
938        Make/O/N=(num) root:myGlobals:Attenuators:ng7att4
939        Make/O/N=(num) root:myGlobals:Attenuators:ng7att5
940        Make/O/N=(num) root:myGlobals:Attenuators:ng7att6
941        Make/O/N=(num) root:myGlobals:Attenuators:ng7att7
942        Make/O/N=(num) root:myGlobals:Attenuators:ng7att8
943        Make/O/N=(num) root:myGlobals:Attenuators:ng7att9
944        Make/O/N=(num) root:myGlobals:Attenuators:ng7att10
945       
946        //NG7 wave has 10 elements, the transmission of att# at the wavelengths
947        //lambda = 5,6,7,8,10,12,14,17,20
948        // note that some of the higher attenuations and ALL of the 20A data is interpolated
949        // none of these values are expected to be used in reality since the flux would be too low in practice
950        Make/O/N=(num) root:myGlobals:Attenuators:ng7lambda={4,5,6,7,8,10,12,14,17,20}
951
952// New calibration, June 2007, John Barker
953        root:myGlobals:Attenuators:ng7att0 = {1, 1, 1, 1, 1, 1, 1, 1 ,1,1}     
954        root:myGlobals:Attenuators:ng7att1 = {0.448656,0.4192,0.3925,0.3661,0.3458,0.3098,0.2922,0.2738,0.2544,0.251352}
955        root:myGlobals:Attenuators:ng7att2 = {0.217193,0.1898,0.1682,0.148,0.1321,0.1076,0.0957,0.08485,0.07479,0.0735965}
956        root:myGlobals:Attenuators:ng7att3 = {0.098019,0.07877,0.06611,0.05429,0.04548,0.03318,0.02798,0.0234,0.02004,0.0202492}
957        root:myGlobals:Attenuators:ng7att4 = {0.0426904,0.03302,0.02617,0.02026,0.0158,0.01052,0.008327,0.006665,0.005745,0.00524807}
958        root:myGlobals:Attenuators:ng7att5 = {0.0194353,0.01398,0.01037,0.0075496,0.005542,0.003339,0.002505,0.001936,0.001765,0.00165959}
959        root:myGlobals:Attenuators:ng7att6 = {0.00971666,0.005979,0.004136,0.002848,0.001946,0.001079,0.0007717,0.000588,0.000487337,0.000447713}
960        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}
961        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}
962        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}
963        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}
964
965// Pre-June 2007 calibration values - do not use these anymore 
966////    root:myGlobals:Attenuators:ng7att0 = {1, 1, 1, 1, 1, 1, 1, 1 ,1}
967////    root:myGlobals:Attenuators:ng7att1 = {0.418, 0.393, 0.369, 0.347, 0.313, 0.291, 0.271, 0.244, 0.219 }
968////    root:myGlobals:Attenuators:ng7att2 = {0.189, 0.167, 0.148, 0.132, 0.109, 0.0945, 0.0830, 0.0681, 0.0560}
969////    root:myGlobals:Attenuators:ng7att3 = {0.0784, 0.0651, 0.0541, 0.0456, 0.0340, 0.0273, 0.0223, 0.0164 , 0.0121}
970////    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}
971////    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}
972////    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}
973////    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}
974////    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}
975////    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}
976////    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}
977End
978
979//returns the transmission of the attenuator (at NG3) given the attenuator number
980//which must be an integer(to select the wave) and given the wavelength.
981//the wavelength may be any value between 5 and 20 (A), and is interpolated
982//between calibrated wavelengths for a given attenuator
983//
984// local function
985//
986Function LookupAttenNG3(lambda,attenNo)
987        Variable lambda, attenNo
988       
989        Variable trans
990        String attStr="root:myGlobals:Attenuators:ng3att"+num2str(trunc(attenNo))
991        String lamStr = "root:myGlobals:Attenuators:ng3lambda"
992       
993        if(attenNo == 0)
994                return (1)              //no attenuation, return trans == 1
995        endif
996       
997        if( (lambda < 5) || (lambda > 20 ) )
998                Abort "Wavelength out of calibration range (5,20). You must manually enter the absolute parameters"
999        Endif
1000       
1001        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) )
1002                Execute "MakeNG3AttenTable()"
1003        Endif
1004        //just in case creating the tables fails....
1005        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) )
1006                Abort "Attenuator lookup waves could not be found. You must manually enter the absolute parameters"
1007        Endif
1008       
1009        //lookup the value by interpolating the wavelength
1010        //the attenuator must always be an integer
1011        Wave att = $attStr
1012        Wave lam = $lamstr
1013        trans = interp(lambda,lam,att)
1014       
1015//      Print "trans = ",trans
1016       
1017        return trans
1018End
1019
1020//returns the transmission of the attenuator (at NG7) given the attenuator number
1021//which must be an integer(to select the wave) and given the wavelength.
1022//the wavelength may be any value between 5 and 20 (A), and is interpolated
1023//between calibrated wavelengths for a given attenuator
1024//
1025// this set of tables is also used for NG5 (NG1) SANS instrument - as the attenuator has yet to be calibrated
1026//
1027// local function
1028//
1029Function LookupAttenNG7(lambda,attenNo)
1030        Variable lambda, attenNo
1031       
1032        Variable trans
1033        String attStr="root:myGlobals:Attenuators:ng7att"+num2str(trunc(attenNo))
1034        String lamStr = "root:myGlobals:Attenuators:ng7lambda"
1035       
1036        if(attenNo == 0)
1037                return (1)              //no attenuation, return trans == 1
1038        endif
1039       
1040        if( (lambda < 5) || (lambda > 20 ) )
1041                Abort "Wavelength out of calibration range (5,20). You must manually enter the absolute parameters"
1042        Endif
1043       
1044        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) )
1045                Execute "MakeNG7AttenTable()"
1046        Endif
1047        //just in case creating the tables fails....
1048        if(!(WaveExists($attStr)) || !(WaveExists($lamStr)) )
1049                Abort "Attenuator lookup waves could not be found. You must manually enter the absolute parameters"
1050        Endif
1051       
1052        //lookup the value by interpolating the wavelength
1053        //the attenuator must always be an integer
1054        Wave att = $attStr
1055        Wave lam = $lamstr
1056        trans = interp(lambda,lam,att)
1057       
1058        //Print "trans = ",trans
1059       
1060        return trans
1061
1062End
1063
1064//returns the proper attenuation factor based on the instrument (NG3, NG5, or NG7)
1065//NG5 values are taken from the NG7 tables (there is very little difference in the
1066//values, and NG5 attenuators have not been calibrated (as of 8/01)
1067//
1068// filestr is passed from TextRead[3] = the default directory
1069// lam is passed from RealsRead[26]
1070// AttenNo is passed from ReaslRead[3]
1071//
1072// Attenuation factor as defined here is <= 1
1073//
1074// ORNL can pass ("",1,attenuationFactor) and have this function simply
1075// spit back the attenuationFactor (that was read into rw[3])
1076//
1077// called by Correct.ipf, ProtocolAsPanel.ipf, Transmission.ipf
1078//
1079Function AttenuationFactor(fileStr,lam,attenNo)
1080        String fileStr
1081        Variable lam,attenNo
1082       
1083        Variable attenFactor=1,loc
1084        String instr=fileStr[1,3]       //filestr is "[NGnSANSn] " or "[NGnSANSnn]" (11 characters total)
1085       
1086        strswitch(instr)
1087                case "NG3":
1088                        attenFactor = LookupAttenNG3(lam,attenNo)
1089                        break
1090                case "NG5":
1091                        //using NG7 lookup Table
1092                        attenFactor = LookupAttenNG7(lam,attenNo)
1093                        break
1094                case "NG7":
1095                        attenFactor = LookupAttenNG7(lam,attenNo)
1096                        break
1097                default:                                                       
1098                        //return error?
1099                        attenFactor=1
1100        endswitch
1101//      print "instr, lambda, attenNo,attenFactor = ",instr,lam,attenNo,attenFactor
1102        return(attenFactor)
1103End
1104
1105//function called by the popups to get a file list of data that can be sorted
1106// this procedure simply removes the raw data files from the string - there
1107//can be lots of other junk present, but this is very fast...
1108//
1109// could also use the alternate procedure of keeping only file with the proper extension
1110//
1111// another possibility is to get a listing of the text files, but is unreliable on
1112// Windows, where the data file must be .txt (and possibly OSX)
1113//
1114// called by FIT_Ops.ipf, NSORT.ipf, PlotUtils.ipf
1115//
1116Function/S ReducedDataFileList(ctrlName)
1117        String ctrlName
1118
1119        String list="",newList="",item=""
1120        Variable num,ii
1121       
1122        //check for the path
1123        PathInfo catPathName
1124        if(V_Flag==0)
1125                DoAlert 0, "Data path does not exist - pick the data path from the button on the main panel"
1126                Return("")
1127        Endif
1128       
1129        list = IndexedFile(catpathName,-1,"????")
1130        num=ItemsInList(list,";")
1131        //print "num = ",num
1132        for(ii=(num-1);ii>=0;ii-=1)
1133                item = StringFromList(ii, list  ,";")
1134                //simply remove all that are not raw data files (SA1 SA2 SA3)
1135                if( !stringmatch(item,"*.SA1*") && !stringmatch(item,"*.SA2*") && !stringmatch(item,"*.SA3*") )
1136                        if( !stringmatch(item,".*") && !stringmatch(item,"*.pxp") && !stringmatch(item,"*.DIV"))                //eliminate mac "hidden" files, pxp, and div files
1137                                newlist += item + ";"
1138                        endif
1139                endif
1140        endfor
1141        //remove VAX version numbers
1142        newList = RemoveVersNumsFromList(newList)
1143        //sort
1144        newList = SortList(newList,";",0)
1145
1146        return newlist
1147End
1148
1149// returns a list of raw data files in the catPathName directory on disk
1150// - list is SEMICOLON-delimited
1151//
1152// does it the "cheap" way, simply finding the ".SAn" in the file name
1153// = does not check for proper byte length.
1154//
1155// called by PatchFiles.ipf, Tile_2D.ipf
1156//
1157Function/S GetRawDataFileList()
1158       
1159        //make sure that path exists
1160        PathInfo catPathName
1161        if (V_flag == 0)
1162                Abort "Folder path does not exist - use Pick Path button on Main Panel"
1163        Endif
1164       
1165        String list=IndexedFile(catPathName,-1,"????")
1166        String newList="",item=""
1167        Variable num=ItemsInList(list,";"),ii
1168        for(ii=0;ii<num;ii+=1)
1169                item = StringFromList(ii, list  ,";")
1170                if( stringmatch(item,"*.sa1*") )
1171                        newlist += item + ";"
1172                endif
1173                if( stringmatch(item,"*.sa2*") )
1174                        newlist += item + ";"
1175                endif
1176                if( stringmatch(item,"*.sa3*") )
1177                        newlist += item + ";"
1178                endif
1179                //print "ii=",ii
1180        endfor
1181        newList = SortList(newList,";",0)
1182        return(newList)
1183End
Note: See TracBrowser for help on using the repository browser.