source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/SANS/FACILITY_Utils.ipf @ 857

Last change on this file since 857 was 857, checked in by srkline, 10 years ago

Added support for reading 4-column data into the 2D reader

Calculation of kappa for ABS now does a specific byte check for ensuring a "good" DIV file. hopefully this will eliminate errors where incorrect DIV files are selected and bad kappa values are generated - and the program thinks (incorrectly) that there is a valid DVI file present, when there really isn't one (and then there is no easy recovery from this)

Added CheckIfDIVData() functions to NCNR_Utils and to FACILITY_Utils, and to other (facility)_Utils

Changed the calls to writing BT5 files after adding so that it could be more easily scripted in the future.

File size: 19.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                                 // number of X and Y pixels
24        Variable/G root:myGlobals:gNPixelsY=128
25       
26        // pixel dimensions are now read directly from the file header.
27//      Variable/G root:myGlobals:PixelResDefault = 0.5                 //pixel resolution in cm
28       
29        Variable/G root:myGlobals:DeadtimeDefault = 3.4e-6              //deadtime in seconds
30
31        Variable/G root:myGlobals:apOff = 5.0           // (cm) distance from sample aperture to sample position
32
33End
34
35
36//**********************
37// Resolution calculation - used by the averaging routines
38// to calculate the resolution function at each q-value
39// - the return value is not used
40//
41// equivalent to John's routine on the VAX Q_SIGMA_AVE.FOR
42// Incorporates eqn. 3-15 from J. Appl. Cryst. (1995) v. 28 p105-114
43//
44// - 21 MAR 07 uses projected BS diameter on the detector
45// - APR 07 still need to add resolution with lenses. currently there is no flag in the
46//          raw data header to indicate the presence of lenses.
47//
48// - Aug 07 - added input to switch calculation based on lenses (==1 if in)
49//
50// - called by CircSectAvg.ipf and RectAnnulAvg.ipf
51//
52// passed values are read from RealsRead
53// except DDet and apOff, which are set from globals before passing
54//
55//
56Function/S getResolution(inQ,lambda,lambdaWidth,DDet,apOff,S1,S2,L1,L2,BS,del_r,usingLenses,SigmaQ,QBar,fSubS)
57        Variable inQ, lambda, lambdaWidth, DDet, apOff, S1, S2, L1, L2, BS, del_r,usingLenses
58        Variable &fSubS, &QBar, &SigmaQ         //these are the output quantities at the input Q value
59       
60        //lots of calculation variables
61        Variable a2, q_small, lp, v_lambda, v_b, v_d, vz, yg, v_g
62        Variable r0, delta, inc_gamma, fr, fv, rmd, v_r1, rm, v_r
63
64        //Constants
65        Variable vz_1 = 3.956e5         //velocity [cm/s] of 1 A neutron
66        Variable g = 981.0                              //gravity acceleration [cm/s^2]
67
68        String results
69        results ="Failure"
70
71        S1 *= 0.5*0.1                   //convert to radius and [cm]
72        S2 *= 0.5*0.1
73
74        L1 *= 100.0                     // [cm]
75        L1 -= apOff                             //correct the distance
76
77        L2 *= 100.0
78        L2 += apOff
79        del_r *= 0.1                            //width of annulus, convert mm to [cm]
80       
81        BS *= 0.5*0.1                   //nominal BS diameter passed in, convert to radius and [cm]
82        // 21 MAR 07 SRK - use the projected BS diameter, based on a point sample aperture
83        Variable LB
84        LB = 20.1 + 1.61*BS                     //distance in cm from beamstop to anode plane (empirical)
85        BS = bs + bs*lb/(l2-lb)         //adjusted diameter of shadow from parallax
86       
87        //Start resolution calculation
88        a2 = S1*L2/L1 + S2*(L1+L2)/L1
89        q_small = 2.0*Pi*(BS-a2)*(1.0-lambdaWidth)/(lambda*L2)
90        lp = 1.0/( 1.0/L1 + 1.0/L2)
91
92        v_lambda = lambdaWidth^2/6.0
93       
94//      if(usingLenses==1)                      //SRK 2007
95        if(usingLenses != 0)                    //SRK 2008 allows for the possibility of different numbers of lenses in header
96                v_b = 0.25*(S1*L2/L1)^2 +0.25*(2/3)*(lambdaWidth/lambda)^2*(S2*L2/lp)^2         //correction to 2nd term
97        else
98                v_b = 0.25*(S1*L2/L1)^2 +0.25*(S2*L2/lp)^2              //original form
99        endif
100       
101        v_d = (DDet/2.3548)^2 + del_r^2/12.0
102        vz = vz_1 / lambda
103        yg = 0.5*g*L2*(L1+L2)/vz^2
104        v_g = 2.0*(2.0*yg^2*v_lambda)                                   //factor of 2 correction, B. Hammouda, 2007
105
106        r0 = L2*tan(2.0*asin(lambda*inQ/(4.0*Pi) ))
107        delta = 0.5*(BS - r0)^2/v_d
108
109        if (r0 < BS)
110                inc_gamma=exp(gammln(1.5))*(1-gammp(1.5,delta))
111        else
112                inc_gamma=exp(gammln(1.5))*(1+gammp(1.5,delta))
113        endif
114
115        fSubS = 0.5*(1.0+erf( (r0-BS)/sqrt(2.0*v_d) ) )
116        if (fSubS <= 0.0)
117                fSubS = 1.e-10
118        endif
119        fr = 1.0 + sqrt(v_d)*exp(-1.0*delta) /(r0*fSubS*sqrt(2.0*Pi))
120        fv = inc_gamma/(fSubS*sqrt(Pi)) - r0^2*(fr-1.0)^2/v_d
121
122        rmd = fr*r0
123        v_r1 = v_b + fv*v_d +v_g
124
125        rm = rmd + 0.5*v_r1/rmd
126        v_r = v_r1 - 0.5*(v_r1/rmd)^2
127        if (v_r < 0.0)
128                v_r = 0.0
129        endif
130        QBar = (4.0*Pi/lambda)*sin(0.5*atan(rm/L2))
131        SigmaQ = QBar*sqrt(v_r/rmd^2 +v_lambda)
132
133        results = "success"
134        Return results
135End
136
137
138//Utility function that returns the detector resolution (in cm)
139//Global values are set in the Initialize procedure
140//
141//
142// - called by CircSectAvg.ipf, RectAnnulAvg.ipf, and ProtocolAsPanel.ipf
143//
144// fileStr is passed as TextRead[3]
145// detStr is passed as TextRead[9]
146//
147// *** as of Jan 2008, depricated. Now detector pixel sizes are read from the file header
148// rw[10] = x size (mm); rw[13] = y size (mm)
149//
150// depricated - pixel dimensions are read directly from the file header
151Function xDetectorPixelResolution(fileStr,detStr)
152        String fileStr,detStr
153       
154        Variable DDet
155
156        //your code here
157       
158        return(DDet)
159End
160
161//Utility function that returns the detector deadtime (in seconds)
162//Global values are set in the Initialize procedure
163//
164// - called by WorkFileUtils.ipf
165//
166// fileStr is passed as TextRead[3] and is the filename
167// detStr is passed as TextRead[9] and is an identifier for the detector
168//
169Function DetectorDeadtime(fileStr,detStr)
170        String fileStr,detStr
171       
172        Variable deadtime
173       
174// your code here
175
176        return(deadtime)
177End
178
179
180// item is a filename
181//
182// this function extracts some sort of number from the file
183// presumably some sort of automatically incrementing run number set by the
184// acquisition system
185//
186// this run number should be a unique identifier for the file
187//
188Function GetRunNumFromFile(item)
189        String item
190
191        Variable num=-1         // an invalid return value
192       
193        //your code here
194       
195        return (num)
196End
197
198// item is a filename
199//
200// this function extracts some sort of number from the file
201// presumably some sort of automatically incrementing run number set by the
202// acquisition system
203//
204// this run number should be a unique identifier for the file
205//
206// same as GetRunNumFromFile(0), just with a string return
207//
208// "ABC" returned as an invalid result
209Function/S GetRunNumStrFromFile(item)
210        String item
211       
212        String invalid = "ABC"  //"ABC" is not a valid run number, since it's text
213        String retStr
214        retStr=invalid
215       
216        //your code here
217       
218        return(retStr)
219End
220
221//returns a string containing the full path to the file containing the
222//run number "num". The null string is returned if no valid file can be found.
223//
224//
225// search in the path "catPathName" (hard-wired), will abort if this path does not exist
226//the file returned will be a RAW SANS data file, other types of files are
227//filtered out.
228//
229// called by Buttons.ipf and Transmission.ipf, and locally by parsing routines
230//
231Function/S FindFileFromRunNumber(num)
232        Variable num
233       
234        String fullName="",partialName="",item=""
235       
236        //make sure that path exists
237        PathInfo catPathName
238        String path = S_path
239        if (V_flag == 0)
240                Abort "folder path does not exist - use Pick Path button"
241        Endif
242
243        //your code here       
244
245        return(fullname)
246       
247End
248
249//function to test a file to see if it is a RAW SANS file
250//
251// returns truth 0/1
252//
253// called by many procedures (both external and local)
254//
255Function CheckIfRawData(fname)
256        String fname
257       
258
259//      if(your test here)
260//              //true, is raw data file
261//              Return(1)
262//      else
263//              //some other file
264//              Return(0)
265//      Endif
266
267End
268
269//function to test a file to see if it is a DIV file
270//
271// returns truth 0/1
272//
273// called by many procedures (both external and local)
274//
275Function CheckIfDIVData(fname)
276        String fname
277       
278
279//      if(your test here)
280//              //true, is DIV data file
281//              Return(1)
282//      else
283//              //some other file
284//              Return(0)
285//      Endif
286
287End
288
289
290// function returns 1 if file is a transmission file, 0 if not
291//
292// called by Transmission.ipf, CatVSTable.ipf, NSORT.ipf
293//
294Function isTransFile(fName)
295        String fname
296       
297//      if(your test here)
298//              //yes, its a transmisison file
299//              Return(1)
300//      else
301//              //some other file
302//              Return(0)
303//      Endif
304End
305
306
307//function to remove all spaces from names when searching for filenames
308//the filename (as saved) will never have interior spaces (TTTTTnnn_AB _Bnnn)
309//but the text field in the header may
310//
311//returns a string identical to the original string, except with the interior spaces removed
312//
313// local function for file name manipulation
314//
315// no change needed here
316Function/S RemoveAllSpaces(str)
317        String str
318       
319        String tempstr = str
320        Variable ii,spc,len             //should never be more than 2 or 3 trailing spaces in a filename
321        ii=0
322        do
323                len = strlen(tempStr)
324                spc = strsearch(tempStr," ",0)          //is the last character a space?
325                if (spc == -1)
326                        break           //no more spaces found, get out
327                endif
328                str = tempstr
329                tempStr = str[0,(spc-1)] + str[(spc+1),(len-1)] //remove the space from the string
330        While(1)        //should never be more than 2 or 3
331       
332        If(strlen(tempStr) < 1)
333                tempStr = ""            //be sure to return a null string if problem found
334        Endif
335       
336        //Print strlen(tempstr)
337       
338        Return(tempStr)
339               
340End
341
342
343//Function attempts to find valid filename from partial name by checking for
344// the existence of the file on disk
345//
346// returns a valid filename (No path prepended) or a null string
347//
348// called by any functions, both external and local
349//
350Function/S FindValidFilename(partialName)
351        String PartialName
352       
353        String retStr=""
354       
355        //your code here
356       
357        return(retStr)
358End
359
360
361//returns a string containing filename (WITHOUT the ;vers)
362//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
363//with the folders separated by colons
364//
365// called by MaskUtils.ipf, ProtocolAsPanel.ipf, WriteQIS.ipf
366//
367// NEEDS NO CHANGES
368//
369Function/S GetFileNameFromPathNoSemi(fullPath)
370        String fullPath
371       
372        Variable offset1,offset2
373        String filename=""
374        //String PartialPath
375        offset1 = 0
376        do
377                offset2 = StrSearch(fullPath, ":", offset1)
378                if (offset2 == -1)                              // no more colons ?
379                        fileName = FullPath[offset1,strlen(FullPath) ]
380                        //PartialPath = FullPath[0, offset1-1]
381                        break
382                endif
383                offset1 = offset2+1
384        while (1)
385       
386        //remove version number from name, if it's there - format should be: filename;N
387        filename =  StringFromList(0,filename,";")              //returns null if error
388       
389        Return filename
390End
391
392//returns a string containing filename (INCLUDING the ;vers)
393//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
394//with the folders separated by colons
395//
396// local, currently unused
397//
398// NEEDS NO CHANGES
399//
400Function/S GetFileNameFromPathKeepSemi(fullPath)
401        String fullPath
402       
403        Variable offset1,offset2
404        String filename
405        //String PartialPath
406        offset1 = 0
407        do
408                offset2 = StrSearch(fullPath, ":", offset1)
409                if (offset2 == -1)                              // no more colons ?
410                        fileName = FullPath[offset1,strlen(FullPath) ]
411                        //PartialPath = FullPath[0, offset1-1]
412                        break
413                endif
414                offset1 = offset2+1
415        while (1)
416       
417        //keep version number from name, if it's there - format should be: filename;N
418       
419        Return filename
420End
421
422//given the full path and filename (fullPath), strips the data path
423//(Mac-style, separated by colons) and returns this path
424//this partial path is the same string that would be returned from PathInfo, for example
425//
426// - allows the user to save to a different path than catPathName
427//
428// called by WriteQIS.ipf
429//
430// NEEDS NO CHANGES
431//
432Function/S GetPathStrFromfullName(fullPath)
433        String fullPath
434       
435        Variable offset1,offset2
436        //String filename
437        String PartialPath
438        offset1 = 0
439        do
440                offset2 = StrSearch(fullPath, ":", offset1)
441                if (offset2 == -1)                              // no more colons ?
442                        //fileName = FullPath[offset1,strlen(FullPath) ]
443                        PartialPath = FullPath[0, offset1-1]
444                        break
445                endif
446                offset1 = offset2+1
447        while (1)
448       
449        Return PartialPath
450End
451
452//given the filename trim or modify the filename to get a new
453//file string that can be used for naming averaged 1-d files
454//
455// called by ProtocolAsPanel.ipf and Tile_2D.ipf
456//
457Function/S GetNameFromHeader(fullName)
458        String fullName
459        String newName = ""
460
461        //your code here
462       
463        Return(newName)
464End
465
466//list (input) is a list, typically returned from IndexedFile()
467//which is semicolon-delimited, and may contain filenames from the VAX
468//that contain version numbers, where the version number appears as a separate list item
469//(and also as a non-existent file)
470//these numbers must be purged from the list, especially for display in a popup
471//or list processing of filenames
472//the function returns the list, cleaned of version numbers (up to 11)
473//raw data files will typically never have a version number other than 1.
474//
475// if there are no version numbers in the list, the input list is returned
476//
477// called by CatVSTable.ipf, NSORT.ipf, Transmission.ipf, WorkFileUtils.ipf
478//
479//
480// NO CHANGE NEEDED
481//
482Function/S RemoveVersNumsFromList(list)
483        String list
484       
485        //get rid of version numbers first (up to 11)
486        Variable ii,num
487        String item
488        num = ItemsInList(list,";")
489        ii=1
490        do
491                item = num2str(ii)
492                list = RemoveFromList(item, list ,";" )
493                ii+=1
494        while(ii<12)
495       
496        return (list)
497End
498
499//input is a list of run numbers, and output is a list of filenames (not the full path)
500//*** input list must be COMMA delimited***
501//output is equivalent to selecting from the CAT table
502//if some or all of the list items are valid filenames, keep them...
503//if an error is encountered, notify of the offending element and return a null list
504//
505//output is COMMA delimited
506//
507// this routine is expecting that the "ask", "none" special cases are handled elsewhere
508//and not passed here
509//
510// called by Marquee.ipf, MultipleReduce.ipf, ProtocolAsPanel.ipf
511//
512// NO CHANGE NEEDED
513//
514Function/S ParseRunNumberList(list)
515        String list
516       
517        String newList="",item="",tempStr=""
518        Variable num,ii,runNum
519       
520        //expand number ranges, if any
521        list = ExpandNumRanges(list)
522       
523        num=itemsinlist(list,",")
524       
525        for(ii=0;ii<num;ii+=1)
526                //get the item
527                item = StringFromList(ii,list,",")
528                //is it already a valid filename?
529                tempStr=FindValidFilename(item) //returns filename if good, null if error
530                if(strlen(tempstr)!=0)
531                        //valid name, add to list
532                        //Print "it's a file"
533                        newList += tempStr + ","
534                else
535                        //not a valid name
536                        //is it a number?
537                        runNum=str2num(item)
538                        //print runnum
539                        if(numtype(runNum) != 0)
540                                //not a number -  maybe an error                       
541                                DoAlert 0,"List item "+item+" is not a valid run number or filename. Please enter a valid number or filename."
542                                return("")
543                        else
544                                //a run number or an error
545                                tempStr = GetFileNameFromPathNoSemi( FindFileFromRunNumber(runNum) )
546                                if(strlen(tempstr)==0)
547                                        //file not found, error
548                                        DoAlert 0,"List item "+item+" is not a valid run number. Please enter a valid number."
549                                        return("")
550                                else
551                                        newList += tempStr + ","
552                                endif
553                        endif
554                endif
555        endfor          //loop over all items in list
556       
557        return(newList)
558End
559
560//takes a comma delimited list that MAY contain number range, and
561//expands any range of run numbers into a comma-delimited list...
562//and returns the new list - if not a range, return unchanged
563//
564// local function
565//
566// NO CHANGE NEEDED
567//
568Function/S ExpandNumRanges(list)
569        String list
570       
571        String newList="",dash="-",item,str
572        Variable num,ii,hasDash
573       
574        num=itemsinlist(list,",")
575//      print num
576        for(ii=0;ii<num;ii+=1)
577                //get the item
578                item = StringFromList(ii,list,",")
579                //does it contain a dash?
580                hasDash = strsearch(item,dash,0)                //-1 if no dash found
581                if(hasDash == -1)
582                        //not a range, keep it in the list
583                        newList += item + ","
584                else
585                        //has a dash (so it's a range), expand (or add null)
586                        newList += ListFromDash(item)           
587                endif
588        endfor
589       
590        return newList
591End
592
593//be sure to add a trailing comma to the return string...
594//
595// local function
596//
597// NO CHANGE NEEDED
598//
599Function/S ListFromDash(item)
600        String item
601       
602        String numList="",loStr="",hiStr=""
603        Variable lo,hi,ii
604       
605        loStr=StringFromList(0,item,"-")        //treat the range as a list
606        hiStr=StringFromList(1,item,"-")
607        lo=str2num(loStr)
608        hi=str2num(hiStr)
609        if( (numtype(lo) != 0) || (numtype(hi) !=0 ) || (lo > hi) )
610                numList=""
611                return numList
612        endif
613        for(ii=lo;ii<=hi;ii+=1)
614                numList += num2str(ii) + ","
615        endfor
616       
617        Return numList
618End
619
620
621//returns the proper attenuation factor based on the instrument
622//
623// filestr is passed from TextRead[3] = the default directory, used to identify the instrument
624// lam is passed from RealsRead[26]
625// AttenNo is passed from ReaslRead[3]
626//
627// Attenuation factor as defined here is <= 1
628//
629// Facilities can pass ("",1,attenuationFactor) and have this function simply
630// spit back the attenuationFactor (that was read into rw[3])
631//
632// called by Correct.ipf, ProtocolAsPanel.ipf, Transmission.ipf
633// atten_err is one std. deviation, passed back by reference
634Function AttenuationFactor(fileStr,lam,attenNo,atten_err)
635        String fileStr
636        Variable lam,attenNo, &atten_err
637       
638        Variable attenFactor=1
639       
640        // your code here
641
642        return(attenFactor)
643End
644
645//function called by the popups to get a file list of data that can be sorted
646// this procedure simply removes the raw data files from the string - there
647//can be lots of other junk present, but this is very fast...
648//
649// could also use the alternate procedure of keeping only file with the proper extension
650//
651// another possibility is to get a listing of the text files, but is unreliable on
652// Windows, where the data file must be .txt (and possibly OSX)
653//
654// called by FIT_Ops.ipf, NSORT.ipf, PlotUtils.ipf
655//
656// modify for specific facilities by changing the "*.SA1*","*.SA2*","*.SA3*" stringmatch
657// items which are specific to NCNR
658//
659Function/S ReducedDataFileList(ctrlName)
660        String ctrlName
661
662        String list="",newList="",item=""
663        Variable num,ii
664       
665        //check for the path
666        PathInfo catPathName
667        if(V_Flag==0)
668                DoAlert 0, "Data path does not exist - pick the data path from the button on the main panel"
669                Return("")
670        Endif
671       
672        list = IndexedFile(catpathName,-1,"????")
673        num=ItemsInList(list,";")
674        //print "num = ",num
675        for(ii=(num-1);ii>=0;ii-=1)
676                item = StringFromList(ii, list  ,";")
677                //simply remove all that are not raw data files (SA1 SA2 SA3)
678                if( !stringmatch(item,"*.SA1*") && !stringmatch(item,"*.SA2*") && !stringmatch(item,"*.SA3*") )
679                        if( !stringmatch(item,".*") && !stringmatch(item,"*.pxp") && !stringmatch(item,"*.DIV"))                //eliminate mac "hidden" files, pxp, and div files
680                                newlist += item + ";"
681                        endif
682                endif
683        endfor
684        //remove VAX version numbers
685        newList = RemoveVersNumsFromList(newList)
686        //sort
687        newList = SortList(newList,";",0)
688
689        return newlist
690End
691
692// returns a list of raw data files in the catPathName directory on disk
693// - list is SEMICOLON-delimited
694//
695// called by PatchFiles.ipf, Tile_2D.ipf
696//
697Function/S GetRawDataFileList()
698       
699        //make sure that path exists
700        PathInfo catPathName
701        if (V_flag == 0)
702                Abort "Folder path does not exist - use Pick Path button on Main Panel"
703        Endif
704       
705        String list=""
706       
707        // your code here
708       
709        return(list)
710End
711
712//**********************
713// 2D resolution function calculation - in terms of X and Y
714//
715// based on notes from David Mildner, 2008
716//
717// the final NCNR version is located in NCNR_Utils.ipf
718//
719Function/S get2DResolution(inQ,phi,lambda,lambdaWidth,DDet,apOff,S1,S2,L1,L2,BS,del_r,usingLenses,r_dist,SigmaQX,SigmaQY,fSubS)
720        Variable inQ, phi,lambda, lambdaWidth, DDet, apOff, S1, S2, L1, L2, BS, del_r,usingLenses,r_dist
721        Variable &SigmaQX,&SigmaQY,&fSubS               //these are the output quantities at the input Q value
722       
723        return("Function Empty")
724End
725
726
727// Return the filename that represents the previous or next file.
728// Input is current filename and increment.
729// Increment should be -1 or 1
730// -1 => previous file
731// 1 => next file
732Function/S GetPrevNextRawFile(curfilename, prevnext)
733        String curfilename
734        Variable prevnext
735
736        String filename
737       
738        //get the run number
739        Variable num = GetRunNumFromFile(curfilename)
740               
741        //find the next specified file by number
742        fileName = FindFileFromRunNumber(num+prevnext)
743
744        if(cmpstr(fileName,"")==0)
745                //null return, do nothing
746                fileName = FindFileFromRunNumber(num)
747        Endif
748
749//      print "in FU "+filename
750
751        Return filename
752End
Note: See TracBrowser for help on using the repository browser.