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

Last change on this file since 430 was 412, checked in by ajj, 14 years ago

More reorg.

File size: 17.7 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma version=5.0
3#pragma IgorVersion=6.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                                 // 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                v_b = 0.25*(S1*L2/L1)^2 +0.25*(2/3)*(lambdaWidth/lambda)^2*(S2*L2/lp)^2         //correction to 2nd term
96        else
97                v_b = 0.25*(S1*L2/L1)^2 +0.25*(S2*L2/lp)^2              //original form
98        endif
99       
100        v_d = (DDet/2.3548)^2 + del_r^2/12.0
101        vz = vz_1 / lambda
102        yg = 0.5*g*L2*(L1+L2)/vz^2
103        v_g = 2.0*(2.0*yg^2*v_lambda)                                   //factor of 2 correction, B. Hammouda, 2007
104
105        r0 = L2*tan(2.0*asin(lambda*inQ/(4.0*Pi) ))
106        delta = 0.5*(BS - r0)^2/v_d
107
108        if (r0 < BS)
109                inc_gamma=exp(gammln(1.5))*(1-gammp(1.5,delta))
110        else
111                inc_gamma=exp(gammln(1.5))*(1+gammp(1.5,delta))
112        endif
113
114        fSubS = 0.5*(1.0+erf( (r0-BS)/sqrt(2.0*v_d) ) )
115        if (fSubS <= 0.0)
116                fSubS = 1.e-10
117        endif
118        fr = 1.0 + sqrt(v_d)*exp(-1.0*delta) /(r0*fSubS*sqrt(2.0*Pi))
119        fv = inc_gamma/(fSubS*sqrt(Pi)) - r0^2*(fr-1.0)^2/v_d
120
121        rmd = fr*r0
122        v_r1 = v_b + fv*v_d +v_g
123
124        rm = rmd + 0.5*v_r1/rmd
125        v_r = v_r1 - 0.5*(v_r1/rmd)^2
126        if (v_r < 0.0)
127                v_r = 0.0
128        endif
129        QBar = (4.0*Pi/lambda)*sin(0.5*atan(rm/L2))
130        SigmaQ = QBar*sqrt(v_r/rmd^2 +v_lambda)
131
132        results = "success"
133        Return results
134End
135
136
137//Utility function that returns the detector resolution (in cm)
138//Global values are set in the Initialize procedure
139//
140// - called by CircSectAvg.ipf, RectAnnulAvg.ipf, and ProtocolAsPanel.ipf
141//
142// fileStr is passed as TextRead[3] and is the filename
143// detStr is passed as TextRead[9] and is an identifier for the detector
144//
145// depricated - pixel dimensions are read directly from the file header
146Function xDetectorPixelResolution(fileStr,detStr)
147        String fileStr,detStr
148       
149        Variable DDet
150
151        //your code here
152       
153        return(DDet)
154End
155
156//Utility function that returns the detector deadtime (in seconds)
157//Global values are set in the Initialize procedure
158//
159// - called by WorkFileUtils.ipf
160//
161// fileStr is passed as TextRead[3] and is the filename
162// detStr is passed as TextRead[9] and is an identifier for the detector
163//
164Function DetectorDeadtime(fileStr,detStr)
165        String fileStr,detStr
166       
167        Variable deadtime
168       
169// your code here
170
171        return(deadtime)
172End
173
174
175// item is a filename
176//
177// this function extracts some sort of number from the file
178// presumably some sort of automatically incrementing run number set by the
179// acquisition system
180//
181// this run number should be a unique identifier for the file
182//
183Function GetRunNumFromFile(item)
184        String item
185
186        Variable num=-1         // an invalid return value
187       
188        //your code here
189       
190        return (num)
191End
192
193// item is a filename
194//
195// this function extracts some sort of number from the file
196// presumably some sort of automatically incrementing run number set by the
197// acquisition system
198//
199// this run number should be a unique identifier for the file
200//
201// same as GetRunNumFromFile(0), just with a string return
202//
203// "ABC" returned as an invalid result
204Function/S GetRunNumStrFromFile(item)
205        String item
206       
207        String invalid = "ABC"  //"ABC" is not a valid run number, since it's text
208        String retStr
209        retStr=invalid
210       
211        //your code here
212       
213        return(retStr)
214End
215
216//returns a string containing the full path to the file containing the
217//run number "num". The null string is returned if no valid file can be found.
218//
219//
220// search in the path "catPathName" (hard-wired), will abort if this path does not exist
221//the file returned will be a RAW SANS data file, other types of files are
222//filtered out.
223//
224// called by Buttons.ipf and Transmission.ipf, and locally by parsing routines
225//
226Function/S FindFileFromRunNumber(num)
227        Variable num
228       
229        String fullName="",partialName="",item=""
230       
231        //make sure that path exists
232        PathInfo catPathName
233        String path = S_path
234        if (V_flag == 0)
235                Abort "folder path does not exist - use Pick Path button"
236        Endif
237
238        //your code here       
239
240        return(fullname)
241       
242End
243
244//function to test a file to see if it is a RAW SANS file
245//
246// returns truth 0/1
247//
248// called by many procedures (both external and local)
249//
250Function CheckIfRawData(fname)
251        String fname
252       
253
254//      if(your test here)
255//              //true, is raw data file
256//              Return(1)
257//      else
258//              //some other file
259//              Return(0)
260//      Endif
261
262End
263
264
265// function returns 1 if file is a transmission file, 0 if not
266//
267// called by Transmission.ipf, CatVSTable.ipf, NSORT.ipf
268//
269Function isTransFile(fName)
270        String fname
271       
272//      if(your test here)
273//              //yes, its a transmisison file
274//              Return(1)
275//      else
276//              //some other file
277//              Return(0)
278//      Endif
279End
280
281
282//function to remove all spaces from names when searching for filenames
283//the filename (as saved) will never have interior spaces (TTTTTnnn_AB _Bnnn)
284//but the text field in the header may
285//
286//returns a string identical to the original string, except with the interior spaces removed
287//
288// local function for file name manipulation
289//
290// no change needed here
291Function/S RemoveAllSpaces(str)
292        String str
293       
294        String tempstr = str
295        Variable ii,spc,len             //should never be more than 2 or 3 trailing spaces in a filename
296        ii=0
297        do
298                len = strlen(tempStr)
299                spc = strsearch(tempStr," ",0)          //is the last character a space?
300                if (spc == -1)
301                        break           //no more spaces found, get out
302                endif
303                str = tempstr
304                tempStr = str[0,(spc-1)] + str[(spc+1),(len-1)] //remove the space from the string
305        While(1)        //should never be more than 2 or 3
306       
307        If(strlen(tempStr) < 1)
308                tempStr = ""            //be sure to return a null string if problem found
309        Endif
310       
311        //Print strlen(tempstr)
312       
313        Return(tempStr)
314               
315End
316
317
318//Function attempts to find valid filename from partial name by checking for
319// the existence of the file on disk
320//
321// returns a valid filename (No path prepended) or a null string
322//
323// called by any functions, both external and local
324//
325Function/S FindValidFilename(partialName)
326        String PartialName
327       
328        String retStr=""
329       
330        //your code here
331       
332        return(retStr)
333End
334
335
336//returns a string containing filename (WITHOUT the ;vers)
337//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
338//with the folders separated by colons
339//
340// called by MaskUtils.ipf, ProtocolAsPanel.ipf, WriteQIS.ipf
341//
342// NEEDS NO CHANGES
343//
344Function/S GetFileNameFromPathNoSemi(fullPath)
345        String fullPath
346       
347        Variable offset1,offset2
348        String filename=""
349        //String PartialPath
350        offset1 = 0
351        do
352                offset2 = StrSearch(fullPath, ":", offset1)
353                if (offset2 == -1)                              // no more colons ?
354                        fileName = FullPath[offset1,strlen(FullPath) ]
355                        //PartialPath = FullPath[0, offset1-1]
356                        break
357                endif
358                offset1 = offset2+1
359        while (1)
360       
361        //remove version number from name, if it's there - format should be: filename;N
362        filename =  StringFromList(0,filename,";")              //returns null if error
363       
364        Return filename
365End
366
367//returns a string containing filename (INCLUDING the ;vers)
368//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
369//with the folders separated by colons
370//
371// local, currently unused
372//
373// NEEDS NO CHANGES
374//
375Function/S GetFileNameFromPathKeepSemi(fullPath)
376        String fullPath
377       
378        Variable offset1,offset2
379        String filename
380        //String PartialPath
381        offset1 = 0
382        do
383                offset2 = StrSearch(fullPath, ":", offset1)
384                if (offset2 == -1)                              // no more colons ?
385                        fileName = FullPath[offset1,strlen(FullPath) ]
386                        //PartialPath = FullPath[0, offset1-1]
387                        break
388                endif
389                offset1 = offset2+1
390        while (1)
391       
392        //keep version number from name, if it's there - format should be: filename;N
393       
394        Return filename
395End
396
397//given the full path and filename (fullPath), strips the data path
398//(Mac-style, separated by colons) and returns this path
399//this partial path is the same string that would be returned from PathInfo, for example
400//
401// - allows the user to save to a different path than catPathName
402//
403// called by WriteQIS.ipf
404//
405// NEEDS NO CHANGES
406//
407Function/S GetPathStrFromfullName(fullPath)
408        String fullPath
409       
410        Variable offset1,offset2
411        //String filename
412        String PartialPath
413        offset1 = 0
414        do
415                offset2 = StrSearch(fullPath, ":", offset1)
416                if (offset2 == -1)                              // no more colons ?
417                        //fileName = FullPath[offset1,strlen(FullPath) ]
418                        PartialPath = FullPath[0, offset1-1]
419                        break
420                endif
421                offset1 = offset2+1
422        while (1)
423       
424        Return PartialPath
425End
426
427//given the filename trim or modify the filename to get a new
428//file string that can be used for naming averaged 1-d files
429//
430// called by ProtocolAsPanel.ipf and Tile_2D.ipf
431//
432Function/S GetNameFromHeader(fullName)
433        String fullName
434        String newName = ""
435
436        //your code here
437       
438        Return(newName)
439End
440
441//list (input) is a list, typically returned from IndexedFile()
442//which is semicolon-delimited, and may contain filenames from the VAX
443//that contain version numbers, where the version number appears as a separate list item
444//(and also as a non-existent file)
445//these numbers must be purged from the list, especially for display in a popup
446//or list processing of filenames
447//the function returns the list, cleaned of version numbers (up to 11)
448//raw data files will typically never have a version number other than 1.
449//
450// if there are no version numbers in the list, the input list is returned
451//
452// called by CatVSTable.ipf, NSORT.ipf, Transmission.ipf, WorkFileUtils.ipf
453//
454//
455// NO CHANGE NEEDED
456//
457Function/S RemoveVersNumsFromList(list)
458        String list
459       
460        //get rid of version numbers first (up to 11)
461        Variable ii,num
462        String item
463        num = ItemsInList(list,";")
464        ii=1
465        do
466                item = num2str(ii)
467                list = RemoveFromList(item, list ,";" )
468                ii+=1
469        while(ii<12)
470       
471        return (list)
472End
473
474//input is a list of run numbers, and output is a list of filenames (not the full path)
475//*** input list must be COMMA delimited***
476//output is equivalent to selecting from the CAT table
477//if some or all of the list items are valid filenames, keep them...
478//if an error is encountered, notify of the offending element and return a null list
479//
480//output is COMMA delimited
481//
482// this routine is expecting that the "ask", "none" special cases are handled elsewhere
483//and not passed here
484//
485// called by Marquee.ipf, MultipleReduce.ipf, ProtocolAsPanel.ipf
486//
487// NO CHANGE NEEDED
488//
489Function/S ParseRunNumberList(list)
490        String list
491       
492        String newList="",item="",tempStr=""
493        Variable num,ii,runNum
494       
495        //expand number ranges, if any
496        list = ExpandNumRanges(list)
497       
498        num=itemsinlist(list,",")
499       
500        for(ii=0;ii<num;ii+=1)
501                //get the item
502                item = StringFromList(ii,list,",")
503                //is it already a valid filename?
504                tempStr=FindValidFilename(item) //returns filename if good, null if error
505                if(strlen(tempstr)!=0)
506                        //valid name, add to list
507                        //Print "it's a file"
508                        newList += tempStr + ","
509                else
510                        //not a valid name
511                        //is it a number?
512                        runNum=str2num(item)
513                        //print runnum
514                        if(numtype(runNum) != 0)
515                                //not a number -  maybe an error                       
516                                DoAlert 0,"List item "+item+" is not a valid run number or filename. Please enter a valid number or filename."
517                                return("")
518                        else
519                                //a run number or an error
520                                tempStr = GetFileNameFromPathNoSemi( FindFileFromRunNumber(runNum) )
521                                if(strlen(tempstr)==0)
522                                        //file not found, error
523                                        DoAlert 0,"List item "+item+" is not a valid run number. Please enter a valid number."
524                                        return("")
525                                else
526                                        newList += tempStr + ","
527                                endif
528                        endif
529                endif
530        endfor          //loop over all items in list
531       
532        return(newList)
533End
534
535//takes a comma delimited list that MAY contain number range, and
536//expands any range of run numbers into a comma-delimited list...
537//and returns the new list - if not a range, return unchanged
538//
539// local function
540//
541// NO CHANGE NEEDED
542//
543Function/S ExpandNumRanges(list)
544        String list
545       
546        String newList="",dash="-",item,str
547        Variable num,ii,hasDash
548       
549        num=itemsinlist(list,",")
550//      print num
551        for(ii=0;ii<num;ii+=1)
552                //get the item
553                item = StringFromList(ii,list,",")
554                //does it contain a dash?
555                hasDash = strsearch(item,dash,0)                //-1 if no dash found
556                if(hasDash == -1)
557                        //not a range, keep it in the list
558                        newList += item + ","
559                else
560                        //has a dash (so it's a range), expand (or add null)
561                        newList += ListFromDash(item)           
562                endif
563        endfor
564       
565        return newList
566End
567
568//be sure to add a trailing comma to the return string...
569//
570// local function
571//
572// NO CHANGE NEEDED
573//
574Function/S ListFromDash(item)
575        String item
576       
577        String numList="",loStr="",hiStr=""
578        Variable lo,hi,ii
579       
580        loStr=StringFromList(0,item,"-")        //treat the range as a list
581        hiStr=StringFromList(1,item,"-")
582        lo=str2num(loStr)
583        hi=str2num(hiStr)
584        if( (numtype(lo) != 0) || (numtype(hi) !=0 ) || (lo > hi) )
585                numList=""
586                return numList
587        endif
588        for(ii=lo;ii<=hi;ii+=1)
589                numList += num2str(ii) + ","
590        endfor
591       
592        Return numList
593End
594
595
596//returns the proper attenuation factor based on the instrument
597//
598// filestr is passed from TextRead[3] = the default directory, used to identify the instrument
599// lam is passed from RealsRead[26]
600// AttenNo is passed from ReaslRead[3]
601//
602// Attenuation factor as defined here is <= 1
603//
604// Facilities can pass ("",1,attenuationFactor) and have this function simply
605// spit back the attenuationFactor (that was read into rw[3])
606//
607// called by Correct.ipf, ProtocolAsPanel.ipf, Transmission.ipf
608//
609Function AttenuationFactor(fileStr,lam,attenNo)
610        String fileStr
611        Variable lam,attenNo
612       
613        Variable attenFactor=1
614       
615        // your code here
616
617        return(attenFactor)
618End
619
620//function called by the popups to get a file list of data that can be sorted
621// this procedure simply removes the raw data files from the string - there
622//can be lots of other junk present, but this is very fast...
623//
624// could also use the alternate procedure of keeping only file with the proper extension
625//
626// another possibility is to get a listing of the text files, but is unreliable on
627// Windows, where the data file must be .txt (and possibly OSX)
628//
629// called by FIT_Ops.ipf, NSORT.ipf, PlotUtils.ipf
630//
631// modify for specific facilities by changing the "*.SA1*","*.SA2*","*.SA3*" stringmatch
632// items which are specific to NCNR
633//
634Function/S ReducedDataFileList(ctrlName)
635        String ctrlName
636
637        String list="",newList="",item=""
638        Variable num,ii
639       
640        //check for the path
641        PathInfo catPathName
642        if(V_Flag==0)
643                DoAlert 0, "Data path does not exist - pick the data path from the button on the main panel"
644                Return("")
645        Endif
646       
647        list = IndexedFile(catpathName,-1,"????")
648        num=ItemsInList(list,";")
649        //print "num = ",num
650        for(ii=(num-1);ii>=0;ii-=1)
651                item = StringFromList(ii, list  ,";")
652                //simply remove all that are not raw data files (SA1 SA2 SA3)
653                if( !stringmatch(item,"*.SA1*") && !stringmatch(item,"*.SA2*") && !stringmatch(item,"*.SA3*") )
654                        if( !stringmatch(item,".*") && !stringmatch(item,"*.pxp") && !stringmatch(item,"*.DIV"))                //eliminate mac "hidden" files, pxp, and div files
655                                newlist += item + ";"
656                        endif
657                endif
658        endfor
659        //remove VAX version numbers
660        newList = RemoveVersNumsFromList(newList)
661        //sort
662        newList = SortList(newList,";",0)
663
664        return newlist
665End
666
667// returns a list of raw data files in the catPathName directory on disk
668// - list is SEMICOLON-delimited
669//
670// called by PatchFiles.ipf, Tile_2D.ipf
671//
672Function/S GetRawDataFileList()
673       
674        //make sure that path exists
675        PathInfo catPathName
676        if (V_flag == 0)
677                Abort "Folder path does not exist - use Pick Path button on Main Panel"
678        Endif
679       
680        String list=""
681       
682        // your code here
683       
684        return(list)
685End
Note: See TracBrowser for help on using the repository browser.