source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/SANS/NCNR_DataReadWrite.ipf @ 1017

Last change on this file since 1017 was 1017, checked in by srkline, 6 years ago

more changes to allow windows to use drives on the network neighborhood rather than force a mapped drive, since window s10 does not have the capability to map a drive.

most I/O operations are fine with either path style, except for GBLoadWave, so this is where the changes are, creating a temporary path if needed, since it seems that GBLoadWave needs either a path, or a non "UNC"-style full path:name specification.

still need to fully test on windows 10

File size: 85.5 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma version=5.0
3#pragma IgorVersion=6.1
4
5//**************************
6//
7// Vers. 1.2 092101
8// Vers. 5.0 29MAR07 - branched from main reduction to split out facility
9//                     specific calls
10//
11// functions for reading raw data files from the VAX
12// - RAW data files are read into the RAW folder - integer data from the detector
13//   is decompressed and given the proper orientation
14// - header information is placed into real,integer, or text waves in the order they appear
15//   in the file header
16//
17// Work data (DIV File) is read into the DIV folder
18//
19//*****************************
20
21//simple, main entry procedure that will load a RAW sans data file (not a work file)
22//into the RAW dataFolder. It is up to the calling procedure to display the file
23//
24// called by MainPanel.ipf and ProtocolAsPanel.ipf
25//
26Function LoadRawSANSData(msgStr)
27        String msgStr
28
29        String filename=""
30
31        //each routine is responsible for checking the current (displayed) data folder
32        //selecting it, and returning to root when done
33        PathInfo/S catPathName          //should set the next dialog to the proper path...
34        //get the filename, then read it in
35        filename = PromptForPath(msgStr)                //in SANS_Utils.ipf
36        //check for cancel from dialog
37        if(strlen(filename)==0)
38                //user cancelled, abort
39                SetDataFolder root:
40                DoAlert 0, "No file selected, action aborted"
41                return(1)
42        Endif
43//      Variable t1=ticks
44        //Print  "GetFileNameFromPath(filename) = " +  GetFileNameFromPathNoSemi(filename)
45        ReadHeaderAndData(filename)     //this is the full Path+file
46
47///***** done by a call to UpdateDisplayInformation()
48//      //the calling macro must change the display type
49//      String/G root:myGlobals:gDataDisplayType="RAW"          //displayed data type is raw
50//     
51//      //data is displayed here
52//      fRawWindowHook()
53
54//      Print "time to load and display (s) = ",(ticks-t1)/60.15
55        Return(0)
56End
57
58
59//function that does the guts of reading the binary data file
60//fname is the full path:name;vers required to open the file
61//VAX record markers are skipped as needed
62//VAX data as read in is in compressed I*2 format, and is decompressed
63//immediately after being read in. The final root:Packages:NIST:RAW:data wave is the real
64//neutron counts and can be directly operated on
65//
66// header information is put into three waves: integersRead, realsRead, and textRead
67// logicals in the header are currently skipped, since they are no use in the
68// data reduction process.
69//
70// The output is the three R/T/I waves that are filled at least with minimal values
71// and the detector data loaded into an array named "data"
72//
73// see documentation for the expected information in each element of the R/T/I waves
74// and the minimum set of information. These waves can be increased in length so that
75// more information can be accessed as needed (propagating changes...)
76//
77// called by multiple .ipfs (when the file name is known)
78//
79Function ReadHeaderAndData(fname)
80        String fname
81        //this function is for reading in RAW data only, so it will always put data in RAW folder
82        String curPath = "root:Packages:NIST:RAW:"
83        SetDataFolder curPath           //use the full path, so it will always work
84        Variable/G root:Packages:NIST:RAW:gIsLogScale = 0               //initial state is linear, keep this in RAW folder
85       
86        Variable refNum,integer,realval
87        String sansfname,textstr
88       
89        Make/O/D/N=23 $"root:Packages:NIST:RAW:IntegersRead"
90        Make/O/D/N=52 $"root:Packages:NIST:RAW:RealsRead"
91        Make/O/T/N=11 $"root:Packages:NIST:RAW:TextRead"
92        Make/O/N=7 $"root:Packages:NIST:RAW:LogicalsRead"
93       
94        Wave intw=$"root:Packages:NIST:RAW:IntegersRead"
95        Wave realw=$"root:Packages:NIST:RAW:RealsRead"
96        Wave/T textw=$"root:Packages:NIST:RAW:TextRead"
97        Wave logw=$"root:Packages:NIST:RAW:LogicalsRead"
98       
99        //***NOTE ****
100        // the "current path" gets mysteriously reset to "root:" after the SECOND pass through
101        // this read routine, after the open dialog is presented
102        // the "--read" waves end up in the correct folder, but the data does not! Why?
103        //must re-set data folder before writing data array (done below)
104       
105        //full filename and path is now passed in...
106        //actually open the file
107        Open/R refNum as fname
108        //skip first two bytes (VAX record length markers, not needed here)
109        FSetPos refNum, 2
110        //read the next 21 bytes as characters (fname)
111        FReadLine/N=21 refNum,textstr
112        textw[0]= textstr
113        //read four i*4 values  /F=3 flag, B=3 flag
114        FBinRead/F=3/B=3 refNum, integer
115        intw[0] = integer
116        //
117        FBinRead/F=3/B=3 refNum, integer
118        intw[1] = integer
119        //
120        FBinRead/F=3/B=3 refNum, integer
121        intw[2] = integer
122        //
123        FBinRead/F=3/B=3 refNum, integer
124        intw[3] = integer
125        // 6 text fields
126        FSetPos refNum,55               //will start reading at byte 56
127        FReadLine/N=20 refNum,textstr
128        textw[1]= textstr
129        FReadLine/N=3 refNum,textstr
130        textw[2]= textstr
131        FReadLine/N=11 refNum,textstr
132        textw[3]= textstr
133        FReadLine/N=1 refNum,textstr
134        textw[4]= textstr
135        FReadLine/N=8 refNum,textstr
136        textw[5]= textstr
137        FReadLine/N=60 refNum,textstr
138        textw[6]= textstr
139       
140        //3 integers
141        FSetPos refNum,174
142        FBinRead/F=3/B=3 refNum, integer
143        intw[4] = integer
144        FBinRead/F=3/B=3 refNum, integer
145        intw[5] = integer
146        FBinRead/F=3/B=3 refNum, integer
147        intw[6] = integer
148       
149        //2 integers, 3 text fields
150        FSetPos refNum,194
151        FBinRead/F=3/B=3 refNum, integer
152        intw[7] = integer
153        FBinRead/F=3/B=3 refNum, integer
154        intw[8] = integer
155        FReadLine/N=6 refNum,textstr
156        textw[7]= textstr
157        FReadLine/N=6 refNum,textstr
158        textw[8]= textstr
159        FReadLine/N=6 refNum,textstr
160        textw[9]= textstr
161       
162        //2 integers
163        FSetPos refNum,244
164        FBinRead/F=3/B=3 refNum, integer
165        intw[9] = integer
166        FBinRead/F=3/B=3 refNum, integer
167        intw[10] = integer
168       
169       
170        //2 integers
171        FSetPos refNum,308
172        FBinRead/F=3/B=3 refNum, integer
173        intw[11] = integer
174        FBinRead/F=3/B=3 refNum, integer
175        intw[12] = integer
176       
177        //2 integers
178        FSetPos refNum,332
179        FBinRead/F=3/B=3 refNum, integer
180        intw[13] = integer
181        FBinRead/F=3/B=3 refNum, integer
182        intw[14] = integer
183       
184        //3 integers
185        FSetPos refNum,376
186        FBinRead/F=3/B=3 refNum, integer
187        intw[15] = integer
188        FBinRead/F=3/B=3 refNum, integer
189        intw[16] = integer
190        FBinRead/F=3/B=3 refNum, integer
191        intw[17] = integer
192       
193        //1 text field - the file association for transmission are the first 4 bytes
194        FSetPos refNum,404
195        FReadLine/N=42 refNum,textstr
196        textw[10]= textstr
197       
198        //1 integer
199        FSetPos refNum,458
200        FBinRead/F=3/B=3 refNum, integer
201        intw[18] = integer
202       
203        //4 integers
204        FSetPos refNum,478
205        FBinRead/F=3/B=3 refNum, integer
206        intw[19] = integer
207        FBinRead/F=3/B=3 refNum, integer
208        intw[20] = integer
209        FBinRead/F=3/B=3 refNum, integer
210        intw[21] = integer
211        FBinRead/F=3/B=3 refNum, integer
212        intw[22] = integer
213
214        //Get Logicals 
215        //Read logicals as int - ICE is writing integers here
216        FSetPos refNum,304
217        FBinRead/F=3/B=3 refNum, integer
218        logw[0] = integer
219        FSetPos refNum,316
220        FBinRead/F=3/B=3 refNum, integer
221        logw[1] = integer       
222        FSetPos refNum,340
223        FBinRead/F=3/B=3 refNum, integer
224        logw[2] = integer
225        FSetPos refNum,344
226        FBinRead/F=3/B=3 refNum, integer
227        logw[3] = integer               
228        FSetPos refNum,446
229        FBinRead/F=3/B=3 refNum, integer
230        logw[4] = integer
231        FSetPos refNum,462
232        FBinRead/F=3/B=3 refNum, integer
233        logw[5] = integer
234        FSetPos refNum,466
235        FBinRead/F=3/B=3 refNum, integer
236        logw[6] = integer               
237
238        Close refNum
239       
240        //now get all of the reals
241        //
242        //Do all the GBLoadWaves at the end
243        //
244        //FBinRead Cannot handle 32 bit VAX floating point
245        //GBLoadWave, however, can properly read it
246        String GBLoadStr="GBLoadWave/O/N=tempGBwave/T={2,2}/J=2/W=1/Q"
247        String strToExecute="",tmpfname=""
248        //append "/S=offset/U=numofreals" to control the read
249        // then append fname to give the full file path
250        // then execute
251       
252        if(cmpstr("\\\\",fname[0,1])==0)        //Windows user going through network neighborhood
253                PathInfo catPathName
254                if(V_flag==1)
255                        //catPathName exists, use it
256                        GBLoadStr += "/P=catPathName"
257                else
258                        // need to create a temporary path
259                        String tmpPathStr = ParseFilePath(1, fname, ":", 1, 0)
260                        NewPath/O/Q tmpUNCPath tmpPathStr
261                        GBLoadStr += "/P=tmpUNCPath"
262                endif
263                tmpfname = ParseFilePath(0, fname, ":", 1, 0)
264        else
265        // original case, fname is the full path:name and is Mac (or a mapped drive)
266                GBLoadStr += ""
267                tmpfname = fname
268        endif
269       
270        Variable a=0,b=0
271       
272        SetDataFolder curPath
273       
274        // 4 R*4 values
275        strToExecute = GBLoadStr + "/S=39/U=4" + "\"" + tmpfname + "\""
276        Execute strToExecute
277        Wave w=$"root:Packages:NIST:RAW:tempGBWave0"
278        b=4     //num of reals read
279        realw[a,a+b-1] = w[p-a]
280        a+=b
281       
282        // 4 R*4 values
283        SetDataFolder curPath
284        strToExecute = GBLoadStr + "/S=158/U=4" + "\"" + tmpfname + "\""
285        Execute strToExecute
286        b=4     
287        realw[a,a+b-1] = w[p-a]
288        a+=b
289
290///////////
291        // 2 R*4 values
292        SetDataFolder curPath
293        strToExecute = GBLoadStr + "/S=186/U=2" + "\"" + tmpfname + "\""
294        Execute strToExecute
295        b=2     
296        realw[a,a+b-1] = w[p-a]
297        a+=b
298
299        // 6 R*4 values
300        SetDataFolder curPath
301        strToExecute = GBLoadStr + "/S=220/U=6" + "\"" + tmpfname + "\""
302        Execute strToExecute
303        b=6     
304        realw[a,a+b-1] = w[p-a]
305        a+=b
306       
307        // 13 R*4 values
308        SetDataFolder curPath
309        strToExecute = GBLoadStr + "/S=252/U=13" + "\"" + tmpfname + "\""
310        Execute strToExecute
311        b=13
312        realw[a,a+b-1] = w[p-a]
313        a+=b
314       
315        // 3 R*4 values
316        SetDataFolder curPath
317        strToExecute = GBLoadStr + "/S=320/U=3" + "\"" + tmpfname + "\""
318        Execute strToExecute
319        b=3     
320        realw[a,a+b-1] = w[p-a]
321        a+=b
322       
323        // 7 R*4 values
324        SetDataFolder curPath
325        strToExecute = GBLoadStr + "/S=348/U=7" + "\"" + tmpfname + "\""
326        Execute strToExecute
327        b=7
328        realw[a,a+b-1] = w[p-a]
329        a+=b
330       
331        // 4 R*4 values
332        SetDataFolder curPath
333        strToExecute = GBLoadStr + "/S=388/U=4" + "\"" + tmpfname + "\""
334        Execute strToExecute
335        b=4     
336        realw[a,a+b-1] = w[p-a]
337        a+=b
338       
339        // 2 R*4 values
340        SetDataFolder curPath
341        strToExecute = GBLoadStr + "/S=450/U=2" + "\"" + tmpfname + "\""
342        Execute strToExecute
343        b=2
344        realw[a,a+b-1] = w[p-a]
345        a+=b
346       
347        // 2 R*4 values
348        SetDataFolder curPath
349        strToExecute = GBLoadStr + "/S=470/U=2" + "\"" + tmpfname + "\""
350        Execute strToExecute
351        b=2
352        realw[a,a+b-1] = w[p-a]
353        a+=b
354       
355        // 5 R*4 values
356        SetDataFolder curPath
357        strToExecute = GBLoadStr + "/S=494/U=5" + "\"" + tmpfname + "\""
358        Execute strToExecute
359        b=5     
360        realw[a,a+b-1] = w[p-a]
361       
362        //if the binary VAX data ws transferred to a MAC, all is OK
363        //if the data was trasnferred to an Intel machine (IBM), all the real values must be
364        //divided by 4 to get the correct floating point values
365        // I can't find any combination of settings in GBLoadWave or FBinRead to read data in correctly
366        // on an Intel machine.
367        //With the corrected version of GBLoadWave XOP (v. 1.43 or higher) Mac and PC both read
368        //VAX reals correctly, and no checking is necessary 12 APR 99
369        //if(cmpstr("Macintosh",IgorInfo(2)) == 0)
370                //do nothing
371        //else
372                //either Windows or Windows NT
373                //realw /= 4
374        //endif
375       
376        SetDataFolder curPath
377        //read in the data
378//      strToExecute = "GBLoadWave/O/N=tempGBwave/B/T={16,2}/S=514/Q/P=catPathName" + "\"" + ParseFilePath(0, fname, ":", 1, 0) + "\""
379        if(cmpstr("\\\\",fname[0,1])==0)        //Windows user going through network neighborhood
380                PathInfo catPathName
381                if(V_flag==1)
382                        //catPathName exists, use it
383                        strToExecute = "GBLoadWave/O/N=tempGBwave/B/T={16,2}/S=514/Q/P=catPathName " + "\"" + ParseFilePath(0, fname, ":", 1, 0) + "\""
384                else
385                        // need to create a temporary path
386                        tmpPathStr = ParseFilePath(1, fname, ":", 1, 0)
387                        NewPath/O/Q tmpUNCPath tmpPathStr
388                        strToExecute = "GBLoadWave/O/N=tempGBwave/B/T={16,2}/S=514/Q/P=tmpUNCPath " + "\"" + ParseFilePath(0, fname, ":", 1, 0) + "\""
389                endif
390        else
391        // original case, fname is the full path:name and is Mac (or a mapped drive)
392                strToExecute = "GBLoadWave/O/N=tempGBwave/B/T={16,2}/S=514/Q " + "\"" + fname + "\""
393        endif
394
395
396        Execute strToExecute
397
398        SetDataFolder curPath           //use the full path, so it will always work
399       
400        Make/O/D/N=16384 $"root:Packages:NIST:RAW:data"
401        WAVE data=$"root:Packages:NIST:RAW:data"
402        SkipAndDecompressVAX(w,data)
403        Redimension/N=(128,128) data                    //NIST raw data is 128x128 - do not generalize
404       
405        Duplicate/O data linear_data                    // at this point, the data is still the raw data, and is linear_data
406       
407        // proper error for counting statistics, good for low count values too
408        // rather than just sqrt(n)
409        // see N. Gehrels, Astrophys. J., 303 (1986) 336-346, equation (7)
410        // for S = 1 in eq (7), this corresponds to one sigma error bars
411        Duplicate/O linear_data linear_data_error
412        linear_data_error = 1 + sqrt(linear_data + 0.75)                               
413        //
414       
415        //keep a string with the filename in the RAW folder
416        String/G root:Packages:NIST:RAW:fileList = textw[0]
417       
418        //set the globals to the detector dimensions (pixels)
419        Variable/G root:myGlobals:gNPixelsX=128         //default for Ordela data (also set in Initialize/NCNR_Utils.ipf)
420        Variable/G root:myGlobals:gNPixelsY=128
421//      if(cmpstr(textW[9],"ILL   ")==0)                //override if OLD Cerca data
422//              Variable/G root:myGlobals:gNPixelsX=64
423//              Variable/G root:myGlobals:gNPixelsY=64
424//      endif
425       
426        //clean up - get rid of w = $"root:Packages:NIST:RAW:tempGBWave0"
427//      KillWaves/Z w
428       
429        //return the data folder to root
430        SetDataFolder root:
431       
432        Return 0
433
434End
435
436
437//function to take the I*2 data that was read in, in VAX format
438//where the integers are "normal", but there are 2-byte record markers
439//sprinkled evenly through the data
440//there are skipped, leaving 128x128=16384 data values
441//the input array (in) is larger than 16384
442//(out) is 128x128 data (single precision) as defined in ReadHeaderAndData()
443//
444// local function to post-process compressed VAX binary data
445//
446//
447Function SkipAndDecompressVAX(in,out)
448        Wave in,out
449       
450        Variable skip,ii
451
452        ii=0
453        skip=0
454        do
455                if(mod(ii+skip,1022)==0)
456                        skip+=1
457                endif
458                out[ii] = Decompress(in[ii+skip])
459                ii+=1
460        while(ii<16384)
461        return(0)
462End
463
464//decompresses each I*2 data value to its real I*4 value
465//using the decompression routine written by Jim Ryhne, many moons ago
466//
467// the compression routine (not shown here, contained in the VAX fortran RW_DATAFILE.FOR) maps I4 to I2 values.
468// (back in the days where disk space *really* mattered). the I4toI2 function spit out:
469// I4toI2 = I4                                                          when I4 in [0,32767]
470// I4toI2 = -777                                                        when I4 in [2,767,000,...]
471// I4toI2 mapped to -13277 to -32768    otherwise
472//
473// the mapped values [-776,-1] and [-13276,-778] are not used.
474// in this compression scheme, only 4 significant digits are retained (to allow room for the exponent)
475// technically, the maximum value should be 2,768,499 since this maps to -32768. But this is of
476// little consequence. If you have individual pixel values on the detector that are that large, you need
477// to re-think your experiment.
478//
479// local function to post-process compressed VAX binary data
480//
481//
482Function Decompress(val)
483        Variable val
484
485        Variable i4,npw,ipw,ib,nd
486
487        ib=10
488        nd=4
489        ipw=ib^nd
490        i4=val
491
492        if (i4 <= -ipw)
493                npw=trunc(-i4/ipw)
494                i4=mod(-i4,ipw)*(ib^npw)
495                return i4
496        else
497                return i4
498        endif
499End
500
501//****************
502//main entry procedure for reading a "WORK.DIV" file
503//displays a quick image of the  file, to check that it's correct
504//data is deposited in root:Packages:NIST:DIV data folder
505//
506// local, currently unused
507//
508//
509Proc ReadWork_DIV()
510//      Silent 1
511       
512        String fname = PromptForPath("Select detector sensitivity file")
513        ReadHeaderAndWork("DIV",fname)          //puts what is read in work.div
514       
515        String waveStr = "root:Packages:NIST:DIV:data"
516//      NewImage/F/K=1/S=2 $waveStr             //this is an experimental IGOR operation
517//      ModifyImage '' ctab= {*,*,YellowHot,0}
518        //Display;AppendImage $waveStr
519       
520        //change the title string to WORK.DIV, rather than PLEXnnn_TST_asdfa garbage
521//      String/G root:Packages:NIST:DIV:fileList = "WORK.DIV"
522        ChangeDisplay("DIV")
523       
524        SetDataFolder root:             //(redundant)
525//      Silent 0
526End
527
528
529//this function is the guts of reading a binary VAX file of real (4-byte) values
530// (i.e. a WORK.aaa file)
531// work files have the same header structure as RAW SANS data, just with
532//different data (real, rather than compressed integer data)
533//
534//************
535//this routine incorrectly reads in several data values where the VAX record
536//marker splits the 4-byte real (at alternating record markers)
537//this error seems to not be severe, but shoud be corrected (at great pain)
538//************
539//
540// called from ProtocolAsPanel.ipf
541//
542//
543Function ReadHeaderAndWork(type,fname)
544        String type,fname
545       
546        //type is the desired folder to read the workfile to
547        //this data will NOT be automatically displayed gDataDisplayType is unchanged
548
549//      SVAR cur_folder=root:myGlobals:gDataDisplayType
550        String cur_folder = type
551        String curPath = "root:Packages:NIST:"+cur_folder
552        SetDataFolder curPath           //use the full path, so it will always work
553       
554        Variable refNum,integer,realval
555        String sansfname,textstr
556        Variable/G $(curPath + ":gIsLogScale") = 0              //initial state is linear, keep this in DIV folder
557       
558        Make/O/D/N=23 $(curPath + ":IntegersRead")
559        Make/O/D/N=52 $(curPath + ":RealsRead")
560        Make/O/T/N=11 $(curPath + ":TextRead")
561       
562        WAVE intw=$(curPath + ":IntegersRead")
563        WAVE realw=$(curPath + ":RealsRead")
564        WAVE/T textw=$(curPath + ":TextRead")
565       
566        //***NOTE ****
567        // the "current path" gets mysteriously reset to "root:" after the SECOND pass through
568        // this read routine, after the open dialog is presented
569        // the "--read" waves end up in the correct folder, but the data does not! Why?
570        //must re-set data folder before writing data array (done below)
571       
572        SetDataFolder curPath
573       
574        //actually open the file
575        Open/R refNum as fname
576        //skip first two bytes
577        FSetPos refNum, 2
578        //read the next 21 bytes as characters (fname)
579        FReadLine/N=21 refNum,textstr
580        textw[0]= textstr
581        //read four i*4 values  /F=3 flag, B=3 flag
582        FBinRead/F=3/B=3 refNum, integer
583        intw[0] = integer
584        //
585        FBinRead/F=3/B=3 refNum, integer
586        intw[1] = integer
587        //
588        FBinRead/F=3/B=3 refNum, integer
589        intw[2] = integer
590        //
591        FBinRead/F=3/B=3 refNum, integer
592        intw[3] = integer
593        // 6 text fields
594        FSetPos refNum,55               //will start reading at byte 56
595        FReadLine/N=20 refNum,textstr
596        textw[1]= textstr
597        FReadLine/N=3 refNum,textstr
598        textw[2]= textstr
599        FReadLine/N=11 refNum,textstr
600        textw[3]= textstr
601        FReadLine/N=1 refNum,textstr
602        textw[4]= textstr
603        FReadLine/N=8 refNum,textstr
604        textw[5]= textstr
605        FReadLine/N=60 refNum,textstr
606        textw[6]= textstr
607       
608        //3 integers
609        FSetPos refNum,174
610        FBinRead/F=3/B=3 refNum, integer
611        intw[4] = integer
612        FBinRead/F=3/B=3 refNum, integer
613        intw[5] = integer
614        FBinRead/F=3/B=3 refNum, integer
615        intw[6] = integer
616       
617        //2 integers, 3 text fields
618        FSetPos refNum,194
619        FBinRead/F=3/B=3 refNum, integer
620        intw[7] = integer
621        FBinRead/F=3/B=3 refNum, integer
622        intw[8] = integer
623        FReadLine/N=6 refNum,textstr
624        textw[7]= textstr
625        FReadLine/N=6 refNum,textstr
626        textw[8]= textstr
627        FReadLine/N=6 refNum,textstr
628        textw[9]= textstr
629       
630        //2 integers
631        FSetPos refNum,244
632        FBinRead/F=3/B=3 refNum, integer
633        intw[9] = integer
634        FBinRead/F=3/B=3 refNum, integer
635        intw[10] = integer
636       
637        //2 integers
638        FSetPos refNum,308
639        FBinRead/F=3/B=3 refNum, integer
640        intw[11] = integer
641        FBinRead/F=3/B=3 refNum, integer
642        intw[12] = integer
643       
644        //2 integers
645        FSetPos refNum,332
646        FBinRead/F=3/B=3 refNum, integer
647        intw[13] = integer
648        FBinRead/F=3/B=3 refNum, integer
649        intw[14] = integer
650       
651        //3 integers
652        FSetPos refNum,376
653        FBinRead/F=3/B=3 refNum, integer
654        intw[15] = integer
655        FBinRead/F=3/B=3 refNum, integer
656        intw[16] = integer
657        FBinRead/F=3/B=3 refNum, integer
658        intw[17] = integer
659       
660        //1 text field - the file association for transmission are the first 4 bytes
661        FSetPos refNum,404
662        FReadLine/N=42 refNum,textstr
663        textw[10]= textstr
664       
665        //1 integer
666        FSetPos refNum,458
667        FBinRead/F=3/B=3 refNum, integer
668        intw[18] = integer
669       
670        //4 integers
671        FSetPos refNum,478
672        FBinRead/F=3/B=3 refNum, integer
673        intw[19] = integer
674        FBinRead/F=3/B=3 refNum, integer
675        intw[20] = integer
676        FBinRead/F=3/B=3 refNum, integer
677        intw[21] = integer
678        FBinRead/F=3/B=3 refNum, integer
679        intw[22] = integer
680       
681        Close refNum
682       
683        //now get all of the reals
684        //
685        //Do all the GBLoadWaves at the end
686        //
687        //FBinRead Cannot handle 32 bit VAX floating point
688        //GBLoadWave, however, can properly read it
689        String GBLoadStr="GBLoadWave/O/N=tempGBwave/T={2,2}/J=2/W=1/Q"
690        String strToExecute="",tmpfname=""
691        //append "/S=offset/U=numofreals" to control the read
692        // then append fname to give the full file path
693        // then execute
694
695        if(cmpstr("\\\\",fname[0,1])==0)        //Windows user going through network neighborhood
696                PathInfo catPathName
697                if(V_flag==1)
698                        //catPathName exists, use it
699                        GBLoadStr += "/P=catPathName"
700                else
701                        // need to create a temporary path
702                        String tmpPathStr = ParseFilePath(1, fname, ":", 1, 0)
703                        NewPath/O/Q tmpUNCPath tmpPathStr
704                        GBLoadStr += "/P=tmpUNCPath"
705                endif
706                tmpfname = ParseFilePath(0, fname, ":", 1, 0)
707        else
708        // original case, fname is the full path:name and is Mac (or a mapped drive)
709                GBLoadStr += ""
710                tmpfname = fname
711        endif
712               
713        Variable a=0,b=0
714       
715        SetDataFolder curPath
716        // 4 R*4 values
717        strToExecute = GBLoadStr + "/S=39/U=4" + "\"" + tmpfname + "\""
718        Execute strToExecute
719       
720        SetDataFolder curPath
721        Wave w=$(curPath + ":tempGBWave0")
722        b=4     //num of reals read
723        realw[a,a+b-1] = w[p-a]
724        a+=b
725       
726        // 4 R*4 values
727        SetDataFolder curPath
728        strToExecute = GBLoadStr + "/S=158/U=4" + "\"" + tmpfname + "\""
729        Execute strToExecute
730        b=4     
731        realw[a,a+b-1] = w[p-a]
732        a+=b
733
734///////////
735        // 2 R*4 values
736        SetDataFolder curPath
737        strToExecute = GBLoadStr + "/S=186/U=2" + "\"" + tmpfname + "\""
738        Execute strToExecute
739        b=2     
740        realw[a,a+b-1] = w[p-a]
741        a+=b
742
743        // 6 R*4 values
744        SetDataFolder curPath
745        strToExecute = GBLoadStr + "/S=220/U=6" + "\"" + tmpfname + "\""
746        Execute strToExecute
747        b=6     
748        realw[a,a+b-1] = w[p-a]
749        a+=b
750       
751        // 13 R*4 values
752        SetDataFolder curPath
753        strToExecute = GBLoadStr + "/S=252/U=13" + "\"" + tmpfname + "\""
754        Execute strToExecute
755        b=13
756        realw[a,a+b-1] = w[p-a]
757        a+=b
758       
759        // 3 R*4 values
760        SetDataFolder curPath
761        strToExecute = GBLoadStr + "/S=320/U=3" + "\"" + tmpfname + "\""
762        Execute strToExecute
763        b=3     
764        realw[a,a+b-1] = w[p-a]
765        a+=b
766       
767        // 7 R*4 values
768        SetDataFolder curPath
769        strToExecute = GBLoadStr + "/S=348/U=7" + "\"" + tmpfname + "\""
770        Execute strToExecute
771        b=7
772        realw[a,a+b-1] = w[p-a]
773        a+=b
774       
775        // 4 R*4 values
776        SetDataFolder curPath
777        strToExecute = GBLoadStr + "/S=388/U=4" + "\"" + tmpfname + "\""
778        Execute strToExecute
779        b=4     
780        realw[a,a+b-1] = w[p-a]
781        a+=b
782       
783        // 2 R*4 values
784        SetDataFolder curPath
785        strToExecute = GBLoadStr + "/S=450/U=2" + "\"" + tmpfname + "\""
786        Execute strToExecute
787        b=2
788        realw[a,a+b-1] = w[p-a]
789        a+=b
790       
791        // 2 R*4 values
792        SetDataFolder curPath
793        strToExecute = GBLoadStr + "/S=470/U=2" + "\"" + tmpfname + "\""
794        Execute strToExecute
795        b=2
796        realw[a,a+b-1] = w[p-a]
797        a+=b
798       
799        // 5 R*4 values
800        SetDataFolder curPath
801        strToExecute = GBLoadStr + "/S=494/U=5" + "\"" + tmpfname + "\""
802        Execute strToExecute
803        b=5     
804        realw[a,a+b-1] = w[p-a]
805       
806        //if the binary VAX data ws transferred to a MAC, all is OK
807        //if the data was trasnferred to an Intel machine (IBM), all the real values must be
808        //divided by 4 to get the correct floating point values
809        // I can't find any combination of settings in GBLoadWave or FBinRead to read data in correctly
810        // on an Intel machine.
811        //With the corrected version of GBLoadWave XOP (v. 1.43 or higher) Mac and PC both read
812        //VAX reals correctly, and no checking is necessary 12 APR 99
813        //if(cmpstr("Macintosh",IgorInfo(2)) == 0)
814                //do nothing
815        //else
816                //either Windows or Windows NT
817                //realw /= 4
818        //endif
819       
820        //read in the data
821        GBLoadStr="GBLoadWave/O/N=tempGBwave/T={2,2}/J=2/W=1/Q"
822
823        if(cmpstr("\\\\",fname[0,1])==0)        //Windows user going through network neighborhood
824                PathInfo catPathName
825                if(V_flag==1)
826                        //catPathName exists, use it
827                        GBLoadStr += "/P=catPathName"
828                else
829                        // need to create a temporary path
830                        tmpPathStr = ParseFilePath(1, fname, ":", 1, 0)
831                        NewPath/O/Q tmpUNCPath tmpPathStr
832                        GBLoadStr += "/P=tmpUNCPath"
833                endif
834                tmpfname = ParseFilePath(0, fname, ":", 1, 0)
835        else
836        // original case, fname is the full path:name and is Mac (or a mapped drive)
837                GBLoadStr += ""
838                tmpfname = fname
839        endif
840
841
842        curPath = "root:Packages:NIST:"+cur_folder
843        SetDataFolder curPath           //use the full path, so it will always work
844       
845        Make/O/D/N=16384 $(curPath + ":data")
846        WAVE data = $(curPath + ":data")
847       
848        Variable skip,ii,offset
849       
850        //read in a total of 16384 values (ii)
851        //as follows :
852        // skip first 2 bytes
853        // skip 512 byte header
854        // skip first 2 bytes of data
855        //(read 511 reals, skip 2b, 510 reals, skip 2b) -16 times = 16336 values
856        // read the final 48 values in seperately to avoid EOF error
857       
858        /////////////
859        SetDataFolder curPath
860        skip = 0
861        ii=0
862        offset = 514 +2
863        a=0
864        do
865                SetDataFolder curPath
866               
867                strToExecute = GBLoadStr + "/S="+num2str(offset)+"/U=511" + "\"" + tmpfname + "\""
868                Execute strToExecute
869                //Print strToExecute
870                b=511
871                data[a,a+b-1] = w[p-a]
872                a+=b
873               
874                offset += 511*4 +2
875               
876                strToExecute = GBLoadStr + "/S="+num2str(offset)+"/U=510" + "\"" + tmpfname + "\""
877                SetDataFolder curPath
878                Execute strToExecute
879                //Print strToExecute
880                b=510
881                data[a,a+b-1] = w[p-a]
882                a+=b
883               
884                offset += 510*4 +2
885               
886                ii+=1
887                //Print "inside do, data[2] =",data[2]
888                //Print "inside do, tempGBwave0[0] = ",w[0]
889        while(ii<16)
890       
891        // 16336 values have been read in --
892        //read in last 64 values
893        strToExecute = GBLoadStr + "/S="+num2str(offset)+"/U=48" + "\"" + tmpfname + "\""
894       
895        SetDataFolder curPath
896        Execute strToExecute
897        b=48
898        data[a,a+b-1] = w[p-a]
899        a+=b
900//
901/// done reading in raw data
902//
903        //Print "in workdatareader , data = ", data[1][1]
904
905        Redimension/n=(128,128) data
906       
907        Duplicate/O data linear_data                    //data read in is on linear scale, copy it now
908       
909        //clean up - get rid of w = $"tempGBWave0"
910        KillWaves w
911       
912        //divide the FP data by 4 if read from a PC (not since GBLoadWave update)
913        //if(cmpstr("Macintosh",IgorInfo(2)) == 0)
914                //do nothing
915        //else
916                //either Windows or Windows NT
917                //data /= 4
918        //endif
919       
920        //keep a string with the filename in the DIV folder
921        String/G $(curPath + ":fileList") = textw[0]
922       
923        //return the data folder to root
924        SetDataFolder root:
925       
926        Return(0)
927End
928
929/////   ASC FORMAT READER  //////
930/////   FOR WORKFILE MATH PANEL //////
931
932//function to read in the ASC output of SANS reduction
933// currently the file has 20 header lines, followed by a single column
934// of 16384 values, Data is written by row, starting with Y=1 and X=(1->128)
935//
936//returns 0 if read was ok
937//returns 1 if there was an error
938//
939// called by WorkFileUtils.ipf
940//
941Function ReadASCData(fname,destPath)
942        String fname, destPath
943        //this function is for reading in ASCII data so put data in user-specified folder
944        SetDataFolder "root:Packages:NIST:"+destPath
945
946        NVAR pixelsX = root:myGlobals:gNPixelsX
947        NVAR pixelsY = root:myGlobals:gNPixelsY
948        Variable refNum=0,ii,p1,p2,tot,num=pixelsX,numHdrLines=20
949        String str=""
950        //data is initially linear scale
951        Variable/G :gIsLogScale=0
952        Make/O/T/N=(numHdrLines) hdrLines
953        Make/O/D/N=(pixelsX*pixelsY) data                       //,linear_data
954       
955        //full filename and path is now passed in...
956        //actually open the file
957//      SetDataFolder destPath
958        Open/R/Z refNum as fname                // /Z flag means I must handle open errors
959        if(refnum==0)           //FNF error, get out
960                DoAlert 0,"Could not find file: "+fname
961                Close/A
962                SetDataFolder root:
963                return(1)
964        endif
965        if(V_flag!=0)
966                DoAlert 0,"File open error: V_flag="+num2Str(V_Flag)
967                Close/A
968                SetDataFolder root:
969                return(1)
970        Endif
971        //
972        for(ii=0;ii<numHdrLines;ii+=1)          //read (or skip) 18 header lines
973                FReadLine refnum,str
974                hdrLines[ii]=str
975        endfor
976        //     
977        Close refnum
978       
979//      SetDataFolder destPath
980        LoadWave/Q/G/D/N=temp fName
981        Wave/Z temp0=temp0
982        data=temp0
983        Redimension/N=(pixelsX,pixelsY) data            //,linear_data
984       
985        Duplicate/O data linear_data
986        Duplicate/O data linear_data_error
987        linear_data_error = 1 + sqrt(data + 0.75)
988       
989        //just in case there are odd inputs to this, like negative intensities
990        WaveStats/Q linear_data_error
991        linear_data_error = numtype(linear_data_error[p]) == 0 ? linear_data_error[p] : V_avg
992        linear_data_error = linear_data_error[p] != 0 ? linear_data_error[p] : V_avg
993       
994        //linear_data = data
995       
996        KillWaves/Z temp0
997       
998        //return the data folder to root
999        SetDataFolder root:
1000       
1001        Return(0)
1002End
1003
1004// fills the "default" fake header so that the SANS Reduction machinery does not have to be altered
1005// pay attention to what is/not to be trusted due to "fake" information.
1006// uses what it can from the header lines from the ASC file (hdrLines wave)
1007//
1008// destFolder is of the form "myGlobals:WorkMath:AAA"
1009//
1010//
1011// called by WorkFileUtils.ipf
1012//
1013Function FillFakeHeader_ASC(destFolder)
1014        String destFolder
1015        Make/O/D/N=23 $("root:Packages:NIST:"+destFolder+":IntegersRead")
1016        Make/O/D/N=52 $("root:Packages:NIST:"+destFolder+":RealsRead")
1017        Make/O/T/N=11 $("root:Packages:NIST:"+destFolder+":TextRead")
1018       
1019        Wave intw=$("root:Packages:NIST:"+destFolder+":IntegersRead")
1020        Wave realw=$("root:Packages:NIST:"+destFolder+":RealsRead")
1021        Wave/T textw=$("root:Packages:NIST:"+destFolder+":TextRead")
1022       
1023        //Put in appropriate "fake" values
1024        //parse values as needed from headerLines
1025        Wave/T hdr=$("root:Packages:NIST:"+destFolder+":hdrLines")
1026        Variable monCt,lam,offset,sdd,trans,thick
1027        Variable xCtr,yCtr,a1,a2,a1a2Dist,dlam,bsDiam
1028        String detTyp=""
1029        String tempStr="",formatStr="",junkStr=""
1030        formatStr = "%g %g %g %g %g %g"
1031        tempStr=hdr[3]
1032        sscanf tempStr, formatStr, monCt,lam,offset,sdd,trans,thick
1033//      Print monCt,lam,offset,sdd,trans,thick,avStr,step
1034        formatStr = "%g %g %g %g %g %g %g %s"
1035        tempStr=hdr[5]
1036        sscanf tempStr,formatStr,xCtr,yCtr,a1,a2,a1a2Dist,dlam,bsDiam,detTyp
1037//      Print xCtr,yCtr,a1,a2,a1a2Dist,dlam,bsDiam,detTyp
1038       
1039        realw[16]=xCtr          //xCtr(pixels)
1040        realw[17]=yCtr  //yCtr (pixels)
1041        realw[18]=sdd           //SDD (m)
1042        realw[26]=lam           //wavelength (A)
1043        //
1044        // necessary values
1045        realw[10]=5                     //detector calibration constants, needed for averaging
1046        realw[11]=10000
1047        realw[12]=0
1048        realw[13]=5
1049        realw[14]=10000
1050        realw[15]=0
1051        //
1052        // used in the resolution calculation, ONLY here to keep the routine from crashing
1053        realw[20]=65            //det size
1054        realw[27]=dlam  //delta lambda
1055        realw[21]=bsDiam        //BS size
1056        realw[23]=a1            //A1
1057        realw[24]=a2    //A2
1058        realw[25]=a1a2Dist      //A1A2 distance
1059        realw[4]=trans          //trans
1060        realw[3]=0              //atten
1061        realw[5]=thick          //thick
1062        //
1063        //
1064        realw[0]=monCt          //def mon cts
1065
1066        // fake values to get valid deadtime and detector constants
1067        //
1068        textw[9]=detTyp+"  "            //6 characters 4+2 spaces
1069        textw[3]="[NGxSANS00]"  //11 chars, NGx will return default values for atten trans, deadtime...
1070       
1071        //set the string values
1072        formatStr="FILE: %s CREATED: %s"
1073        sscanf hdr[0],formatStr,tempStr,junkStr
1074//      Print tempStr
1075//      Print junkStr
1076        String/G $("root:Packages:NIST:"+destFolder+":fileList") = tempStr
1077        textw[0] = tempStr              //filename
1078        textw[1] = junkStr              //run date-time
1079       
1080        //file label = hdr[1]
1081        tempStr = hdr[1]
1082        tempStr = tempStr[0,strlen(tempStr)-2]          //clean off the last LF
1083//      Print tempStr
1084        textW[6] = tempStr      //sample label
1085       
1086        return(0)
1087End
1088
1089
1090/////*****************
1091////unused testing procedure for writing a 4 byte floating point value in VAX format
1092//Proc TestReWriteReal()
1093//      String Path
1094//      Variable value,start
1095//     
1096//      GetFileAndPath()
1097//      Path = S_Path + S_filename
1098//     
1099//      value = 0.2222
1100//      start = 158             //trans starts at byte 159
1101//      ReWriteReal(path,value,start)
1102//     
1103//      SetDataFolder root:
1104//End
1105
1106//function will re-write a real value (4bytes) to the header of a RAW data file
1107//to ensure re-readability, the real value must be written mimicking VAX binary format
1108//which is done in this function
1109//path is the full path:file;vers to the file
1110//value is the real value to write
1111//start is the position to move the file marker to, to begin writing
1112//--so start is actually the "end byte" of the previous value
1113//
1114// Igor cannot write VAX FP values - so to "fake it"
1115// (1) write IEEE FP, 4*desired value, little endian
1116// (2) read back as two 16-bit integers, big endian
1117// (3) write the two 16-bit integers, reversed, writing each as big endian
1118//
1119//this procedure takes care of all file open/close pairs needed
1120//
1121Function WriteVAXReal(path,value,start)
1122        String path
1123        Variable value,start
1124       
1125        //Print " in F(), path = " + path
1126        Variable refnum,int1,int2, value4
1127
1128//////
1129        value4 = 4*value
1130       
1131        Open/A/T="????TEXT" refnum as path
1132        //write IEEE FP, 4*desired value
1133        FSetPos refnum,start
1134        FBinWrite/B=3/F=4 refnum,value4         //write out as little endian
1135        //move to the end of the file
1136        FStatus refnum
1137        FSetPos refnum,V_logEOF
1138        Close refnum
1139       
1140///////
1141        Open/R refnum as path
1142        //read back as two 16-bit integers
1143        FSetPos refnum,start
1144        FBinRead/B=2/F=2 refnum,int1    //read as big-endian
1145        FBinRead/B=2/F=2 refnum,int2   
1146        //file was opened read-only, no need to move to the end of the file, just close it     
1147        Close refnum
1148       
1149///////
1150        Open/A/T="????TEXT" refnum as path
1151        //write the two 16-bit integers, reversed
1152        FSetPos refnum,start
1153        FBinWrite/B=2/F=2 refnum,int2   //re-write as big endian
1154        FBinWrite/B=2/F=2 refnum,int1
1155        //move to the end of the file
1156        FStatus refnum
1157        FSetPos refnum,V_logEOF
1158        Close refnum            //at this point, it is as the VAX would have written it.
1159       
1160        Return(0)
1161End
1162
1163//sample transmission is a real value at byte 158
1164Function WriteTransmissionToHeader(fname,trans)
1165        String fname
1166        Variable trans
1167       
1168        WriteVAXReal(fname,trans,158)           //transmission start byte is 158
1169        return(0)
1170End
1171
1172//sample transmission error (one sigma) is a real value at byte 396
1173Function WriteTransmissionErrorToHeader(fname,transErr)
1174        String fname
1175        Variable transErr
1176       
1177        WriteVAXReal(fname,transErr,396)                //transmission start byte is 396
1178        return(0)
1179End
1180
1181
1182//whole transmission is a real value at byte 392
1183Function WriteWholeTransToHeader(fname,trans)
1184        String fname
1185        Variable trans
1186       
1187        WriteVAXReal(fname,trans,392)           //transmission start byte is 392
1188        return(0)
1189End
1190
1191//box sum counts is a real value at byte 494
1192Function WriteBoxCountsToHeader(fname,counts)
1193        String fname
1194        Variable counts
1195       
1196        WriteVAXReal(fname,counts,494)          // start byte is 494
1197        return(0)
1198End
1199
1200//box sum counts error is is a real value at byte 400
1201Function WriteBoxCountsErrorToHeader(fname,rel_err)
1202        String fname
1203        Variable rel_err
1204       
1205        WriteVAXReal(fname,rel_err,400)         // start byte is 400
1206        return(0)
1207End
1208
1209//beam stop X-pos is at byte 368
1210Function WriteBSXPosToHeader(fname,xpos)
1211        String fname
1212        Variable xpos
1213       
1214        WriteVAXReal(fname,xpos,368)
1215        return(0)
1216End
1217
1218//sample thickness is at byte 162
1219Function WriteThicknessToHeader(fname,num)
1220        String fname
1221        Variable num
1222       
1223        WriteVAXReal(fname,num,162)
1224        return(0)
1225End
1226
1227//beam center X pixel location is at byte 252
1228Function WriteBeamCenterXToHeader(fname,num)
1229        String fname
1230        Variable num
1231       
1232        WriteVAXReal(fname,num,252)
1233        return(0)
1234End
1235
1236//beam center Y pixel location is at byte 256
1237Function WriteBeamCenterYToHeader(fname,num)
1238        String fname
1239        Variable num
1240       
1241        WriteVAXReal(fname,num,256)
1242        return(0)
1243End
1244
1245//attenuator number (not its transmission) is at byte 51
1246Function WriteAttenNumberToHeader(fname,num)
1247        String fname
1248        Variable num
1249       
1250        WriteVAXReal(fname,num,51)
1251        return(0)
1252End
1253
1254//monitor count is at byte 39
1255Function WriteMonitorCountToHeader(fname,num)
1256        String fname
1257        Variable num
1258       
1259        WriteVAXReal(fname,num,39)
1260        return(0)
1261End
1262
1263//total detector count is at byte 47
1264Function WriteDetectorCountToHeader(fname,num)
1265        String fname
1266        Variable num
1267       
1268        WriteVAXReal(fname,num,47)
1269        return(0)
1270End
1271
1272//transmission detector count is at byte 388
1273Function WriteTransDetCountToHeader(fname,num)
1274        String fname
1275        Variable num
1276       
1277        WriteVAXReal(fname,num,388)
1278        return(0)
1279End
1280
1281//wavelength is at byte 292
1282Function WriteWavelengthToHeader(fname,num)
1283        String fname
1284        Variable num
1285       
1286        WriteVAXReal(fname,num,292)
1287        return(0)
1288End
1289
1290//wavelength spread is at byte 296
1291Function WriteWavelengthDistrToHeader(fname,num)
1292        String fname
1293        Variable num
1294       
1295        WriteVAXReal(fname,num,296)
1296        return(0)
1297End
1298
1299//temperature is at byte 186
1300Function WriteTemperatureToHeader(fname,num)
1301        String fname
1302        Variable num
1303       
1304        WriteVAXReal(fname,num,186)
1305        return(0)
1306End
1307
1308//magnetic field is at byte 190
1309Function WriteMagnFieldToHeader(fname,num)
1310        String fname
1311        Variable num
1312       
1313        WriteVAXReal(fname,num,190)
1314        return(0)
1315End
1316
1317//Source Aperture diameter is at byte 280
1318Function WriteSourceApDiamToHeader(fname,num)
1319        String fname
1320        Variable num
1321       
1322        WriteVAXReal(fname,num,280)
1323        return(0)
1324End
1325
1326//Sample Aperture diameter is at byte 284
1327Function WriteSampleApDiamToHeader(fname,num)
1328        String fname
1329        Variable num
1330       
1331        WriteVAXReal(fname,num,284)
1332        return(0)
1333End
1334
1335//Source to sample distance is at byte 288
1336Function WriteSrcToSamDistToHeader(fname,num)
1337        String fname
1338        Variable num
1339       
1340        WriteVAXReal(fname,num,288)
1341        return(0)
1342End
1343
1344//detector offset is at byte 264
1345Function WriteDetectorOffsetToHeader(fname,num)
1346        String fname
1347        Variable num
1348       
1349        WriteVAXReal(fname,num,264)
1350        return(0)
1351End
1352
1353//beam stop diameter is at byte 272
1354Function WriteBeamStopDiamToHeader(fname,num)
1355        String fname
1356        Variable num
1357       
1358        WriteVAXReal(fname,num,272)
1359        return(0)
1360End
1361
1362//sample to detector distance is at byte 260
1363Function WriteSDDToHeader(fname,num)
1364        String fname
1365        Variable num
1366       
1367        WriteVAXReal(fname,num,260)
1368        return(0)
1369End
1370
1371//detector pixel X size (mm) is at byte 220
1372Function WriteDetPixelXToHeader(fname,num)
1373        String fname
1374        Variable num
1375       
1376        WriteVAXReal(fname,num,220)
1377        return(0)
1378End
1379
1380//detector pixel Y size (mm) is at byte 232
1381Function WriteDetPixelYToHeader(fname,num)
1382        String fname
1383        Variable num
1384       
1385        WriteVAXReal(fname,num,232)
1386        return(0)
1387End
1388
1389// Write the detector deadtime to the file header (in seconds) @ byte 498
1390Function WriteDeadtimeToHeader(fname,num)
1391        String fname
1392        Variable num
1393       
1394        WriteVAXReal(fname,num,498)
1395        return(0)
1396End
1397
1398
1399
1400//rewrite a text field back to the header
1401// fname is the full path:name
1402// str is the CORRECT length - it will all be written - pad or trim before passing
1403// start is the start byte
1404Function WriteTextToHeader(fname,str,start)
1405        String fname,str
1406        Variable start
1407       
1408        Variable refnum
1409        Open/A/T="????TEXT" refnum as fname      //Open for writing! Move to EOF before closing!
1410        FSetPos refnum,start
1411        FBinWrite/F=0 refnum, str      //native object format (character)
1412        //move to the end of the file before closing
1413        FStatus refnum
1414        FSetPos refnum,V_logEOF
1415        Close refnum
1416               
1417        return(0)
1418end
1419
1420// sample label, starts at byte 98
1421// limit to 60 characters
1422Function WriteSamLabelToHeader(fname,str)
1423        String fname,str
1424       
1425        if(strlen(str) > 60)
1426                str = str[0,59]
1427        endif
1428        WriteTextToHeader(fname,str,98)
1429        return(0)
1430End
1431
1432//user account name, starts at byte 78
1433// limit to 11 characters
1434Function WriteAcctNameToHeader(fname,str)
1435        String fname,str
1436       
1437        if(strlen(str) > 9)
1438                str = str[0,8]
1439        endif
1440        str = "["+str+"]"
1441       
1442        if(strlen(str) < 11)            //pad to 11 characters if the account number is only one digit
1443                str = PadString(str,11,0x20)
1444        endif
1445               
1446        WriteTextToHeader(fname,str,78)
1447        return(0)
1448End
1449
1450// file name, starts at byte 2
1451// limit to 21 characters
1452//
1453// be sure that any white space to pad to 21 characters is at the front of the string
1454Function WriteFileNameToHeader(fname,str)
1455        String fname,str
1456       
1457        Variable i
1458        String newStr=""
1459//      printf "\"%s\"\t%d\r",str,strlen(str)
1460
1461        //strip any white spaces from the end (from TrimWSR(str) in cansasXML.ipf)
1462        for (i=strlen(str)-1; char2num(str[i])<=32 && i>=0; i-=1)    // find last non-white space
1463        endfor
1464        str = str[0,i]
1465//      printf "\"%s\"\t%d\r",str,strlen(str)
1466
1467        // if the string is less than 21 characters, fix it with white space at the beginning
1468        if(strlen(str) < 21)
1469                newStr = PadString(newStr,21,0x20)              //pad with fortran-style spaces
1470                newStr[21-strlen(str),20] = str
1471        else
1472                newStr = str
1473        endif
1474//      printf "\"%s\"\t%d\r",newstr,strlen(newstr)
1475
1476        WriteTextToHeader(fname,newstr,2)
1477        return(0)
1478End
1479
1480
1481//rewrite an integer field back to the header
1482// fname is the full path:name
1483// val is the integer value
1484// start is the start byte
1485Function RewriteIntegerToHeader(fname,val,start)
1486        String fname
1487        Variable val,start
1488       
1489        Variable refnum
1490        Open/A/T="????TEXT" refnum as fname      //Open for writing! Move to EOF before closing!
1491        FSetPos refnum,start
1492        FBinWrite/B=3/F=3 refnum, val      //write a 4-byte integer
1493        //move to the end of the file before closing
1494        FStatus refnum
1495        FSetPos refnum,V_logEOF
1496        Close refnum
1497               
1498        return(0)
1499end
1500
1501Function WriteCountTimeToHeader(fname,num)
1502        String fname
1503        Variable num
1504       
1505        RewriteIntegerToHeader(fname,num,31)
1506        return(0)
1507End
1508
1509// read specific bits of information from the header
1510// each of these operations MUST take care of open/close on their own
1511
1512Function/S getStringFromHeader(fname,start,num)
1513        String fname                            //full path:name
1514        Variable start,num              //starting byte and number of characters to read
1515       
1516        String str
1517        Variable refnum
1518        Open/R refNum as fname
1519        FSetPos refNum,start
1520        FReadLine/N=(num) refNum,str
1521        Close refnum
1522       
1523        return(str)
1524End
1525
1526// file suffix (4 characters @ byte 19)
1527Function/S getSuffix(fname)
1528        String fname
1529       
1530        return(getStringFromHeader(fname,19,4))
1531End
1532
1533// associated file suffix (for transmission) (4 characters @ byte 404)
1534Function/S getAssociatedFileSuffix(fname)
1535        String fname
1536       
1537        return(getStringFromHeader(fname,404,4))
1538End
1539
1540// sample label (60 characters @ byte 98)
1541Function/S getSampleLabel(fname)
1542        String fname
1543       
1544        return(getStringFromHeader(fname,98,60))
1545End
1546
1547// file creation date (20 characters @ byte 55)
1548Function/S getFileCreationDate(fname)
1549        String fname
1550       
1551        return(getStringFromHeader(fname,55,20))
1552End
1553
1554// user account (11 characters @ byte 78)
1555Function/S getAcctName(fname)
1556        String fname
1557       
1558        return(getStringFromHeader(fname,78,11))
1559End
1560
1561// file name (21 characters @ byte 2)
1562Function/S getFileName(fname)
1563        String fname
1564       
1565        return(getStringFromHeader(fname,2,21))
1566End
1567
1568
1569// read a single real value with GBLoadWave
1570// SRK 2016 changed to use the path, which may be UNC (that is starting with \\ on windows 10)
1571//
1572//
1573Function getRealValueFromHeader(fname,start)
1574        String fname
1575        Variable start
1576
1577        String GBLoadStr="GBLoadWave/O/N=tempGBwave/T={2,2}/J=2/W=1/Q" 
1578       
1579        if(cmpstr("\\\\",fname[0,1])==0)        //Windows user going through network neighborhood
1580                PathInfo catPathName
1581                if(V_flag==1)
1582                        //catPathName exists, use it
1583                        GBLoadStr += "/S="+num2str(start)+"/U=1/P=catPathName " + "\"" + ParseFilePath(0, fname, ":", 1, 0) + "\""
1584                else
1585                        // need to create a temporary path
1586                        String tmpPathStr = ParseFilePath(1, fname, ":", 1, 0)
1587                        NewPath/O/Q tmpUNCPath tmpPathStr
1588                        GBLoadStr += "/S="+num2str(start)+"/U=1/P=tmpUNCPath " + "\"" + ParseFilePath(0, fname, ":", 1, 0) + "\""
1589                endif
1590        else
1591        // original case, fname is the full path:name and is Mac (or a mapped drive)
1592                GBLoadStr += "/S="+num2str(start)+"/U=1" + "\"" + fname + "\""
1593        endif
1594       
1595       
1596        Execute GBLoadStr
1597        Wave w=$"tempGBWave0"
1598       
1599        KillPath/Z tmpUNCPath
1600       
1601        return(w[0])
1602End
1603
1604//monitor count is at byte 39
1605Function getMonitorCount(fname)
1606        String fname
1607       
1608        return(getRealValueFromHeader(fname,39))
1609end
1610
1611//saved monitor count is at byte 43
1612Function getSavMon(fname)
1613        String fname
1614       
1615        return(getRealValueFromHeader(fname,43))
1616end
1617
1618//detector count is at byte 47
1619Function getDetCount(fname)
1620        String fname
1621       
1622        return(getRealValueFromHeader(fname,47))
1623end
1624
1625//Attenuator number is at byte 51
1626Function getAttenNumber(fname)
1627        String fname
1628       
1629        return(getRealValueFromHeader(fname,51))
1630end
1631
1632//transmission is at byte 158
1633Function getSampleTrans(fname)
1634        String fname
1635       
1636        return(getRealValueFromHeader(fname,158))
1637end
1638
1639//transmission error (one sigma) is at byte 396
1640Function getSampleTransError(fname)
1641        String fname
1642       
1643        return(getRealValueFromHeader(fname,396))
1644end
1645
1646//box counts are stored at byte 494
1647Function getBoxCounts(fname)
1648        String fname
1649       
1650        return(getRealValueFromHeader(fname,494))
1651end
1652
1653//box counts error are stored at byte 400
1654Function getBoxCountsError(fname)
1655        String fname
1656       
1657        return(getRealValueFromHeader(fname,400))
1658end
1659
1660
1661//whole detector trasmission is at byte 392
1662Function getSampleTransWholeDetector(fname)
1663        String fname
1664       
1665        return(getRealValueFromHeader(fname,392))
1666end
1667
1668//SampleThickness is at byte 162
1669Function getSampleThickness(fname)
1670        String fname
1671       
1672        return(getRealValueFromHeader(fname,162))
1673end
1674
1675//Sample Rotation Angle is at byte 170
1676Function getSampleRotationAngle(fname)
1677        String fname
1678       
1679        return(getRealValueFromHeader(fname,170))
1680end
1681
1682//Sample position in changer
1683Function getSamplePosition(fname)
1684        String fname
1685       
1686        return(getRealValueFromHeader(fname,166))
1687end
1688
1689//temperature is at byte 186
1690Function getTemperature(fname)
1691        String fname
1692       
1693        return(getRealValueFromHeader(fname,186))
1694end
1695
1696//field strength is at byte 190
1697// 190 is not the right location, 348 looks to be correct for the electromagnets, 450 for the
1698// superconducting magnet. Although each place is only the voltage, it is correct
1699Function getFieldStrength(fname)
1700        String fname
1701       
1702//      return(getRealValueFromHeader(fname,190))
1703        return(getRealValueFromHeader(fname,348))
1704end
1705
1706//beam xPos is at byte 252
1707Function getBeamXPos(fname)
1708        String fname
1709       
1710        return(getRealValueFromHeader(fname,252))
1711end
1712
1713//beam Y pos is at byte 256
1714Function getBeamYPos(fname)
1715        String fname
1716       
1717        return(getRealValueFromHeader(fname,256))
1718end
1719
1720//sample to detector distance is at byte 260
1721Function getSDD(fname)
1722        String fname
1723       
1724        return(getRealValueFromHeader(fname,260))
1725end
1726
1727//detector offset is at byte 264
1728Function getDetectorOffset(fname)
1729        String fname
1730       
1731        return(getRealValueFromHeader(fname,264))
1732end
1733
1734//Beamstop diameter is at byte 272
1735Function getBSDiameter(fname)
1736        String fname
1737       
1738        return(getRealValueFromHeader(fname,272))
1739end
1740
1741//source aperture diameter is at byte 280
1742Function getSourceApertureDiam(fname)
1743        String fname
1744       
1745        return(getRealValueFromHeader(fname,280))
1746end
1747
1748//sample aperture diameter is at byte 284
1749Function getSampleApertureDiam(fname)
1750        String fname
1751       
1752        return(getRealValueFromHeader(fname,284))
1753end
1754
1755//source AP to Sample AP distance is at byte 288
1756Function getSourceToSampleDist(fname)
1757        String fname
1758       
1759        return(getRealValueFromHeader(fname,288))
1760end
1761
1762//wavelength is at byte 292
1763Function getWavelength(fname)
1764        String fname
1765       
1766        return(getRealValueFromHeader(fname,292))
1767end
1768
1769//wavelength spread is at byte 296
1770Function getWavelengthSpread(fname)
1771        String fname
1772       
1773        return(getRealValueFromHeader(fname,296))
1774end
1775
1776//transmission detector count is at byte 388
1777Function getTransDetectorCounts(fname)
1778        String fname
1779       
1780        return(getRealValueFromHeader(fname,388))
1781end
1782
1783//detector pixel X size is at byte 220
1784Function getDetectorPixelXSize(fname)
1785        String fname
1786       
1787        return(getRealValueFromHeader(fname,220))
1788end
1789
1790//detector pixel Y size is at byte 232
1791Function getDetectorPixelYSize(fname)
1792        String fname
1793       
1794        return(getRealValueFromHeader(fname,232))
1795end
1796
1797// stub for ILL - power is written to their header, not ours
1798Function getReactorPower(fname)
1799        String fname
1800
1801        return 0
1802
1803end
1804
1805// read the detector deadtime (in seconds)
1806Function getDetectorDeadtime(fname)
1807        String fname
1808       
1809        return(getRealValueFromHeader(fname,498))
1810end
1811
1812
1813
1814
1815//////  integer values
1816// reads 32 bit integer
1817Function getIntegerFromHeader(fname,start)
1818        String fname                            //full path:name
1819        Variable start          //starting byte
1820       
1821        Variable refnum,val
1822        Open/R refNum as fname
1823        FSetPos refNum,start
1824        FBinRead/B=3/F=3 refnum,val
1825        Close refnum
1826       
1827        return(val)
1828End
1829
1830//total count time is at byte 31       
1831Function getCountTime(fname)
1832        String fname
1833        return(getIntegerFromHeader(fname,31))
1834end
1835
1836
1837//reads the wavelength from a reduced data file (not very reliable)
1838// - does not work with NSORTed files
1839// - only used in FIT/RPA (which itself is almost NEVER used...)
1840//
1841Function GetLambdaFromReducedData(tempName)
1842        String tempName
1843       
1844        String junkString
1845        Variable lambdaFromFile, fileVar
1846        lambdaFromFile = 6.0
1847        Open/R/P=catPathName fileVar as tempName
1848        FReadLine fileVar, junkString
1849        FReadLine fileVar, junkString
1850        FReadLine fileVar, junkString
1851        if(strsearch(LowerStr(junkString),"lambda",0) != -1)
1852                FReadLine/N=11 fileVar, junkString
1853                FReadLine/N=10 fileVar, junkString
1854                lambdaFromFile = str2num(junkString)
1855        endif
1856        Close fileVar
1857       
1858        return(lambdaFromFile)
1859End
1860
1861/////   TRANSMISSION RELATED FUNCTIONS    ////////
1862//box coordinate are returned by reference
1863// filename is the full path:name
1864Function getXYBoxFromFile(filename,x1,x2,y1,y2)
1865        String filename
1866        Variable &x1,&x2,&y1,&y2
1867       
1868        Variable refnum
1869//      String tmpFile = FindValidFilename(filename)
1870               
1871//      Open/R/P=catPathName refnum as tmpFile
1872        Open/R refnum as filename
1873        FSetPos refnum,478
1874        FBinRead/F=3/B=3 refnum, x1
1875        FBinRead/F=3/B=3 refnum, x2
1876        FBinRead/F=3/B=3 refnum, y1
1877        FBinRead/F=3/B=3 refnum, y2
1878        Close refnum
1879       
1880        return(0)
1881End
1882
1883//go find the file, open it and write 4 integers to the file
1884//in the positions for analysis.rows(2), .cols(2) = 4 unused 4byte integers
1885Function WriteXYBoxToHeader(filename,x1,x2,y1,y2)
1886        String filename
1887        Variable x1,x2,y1,y2
1888       
1889        Variable refnum
1890        Open/A/T="????TEXT" refnum as filename
1891        FSetPos refnum,478
1892        FBinWrite/F=3/B=3 refNum, x1
1893        FBinWrite/F=3/B=3 refNum, x2
1894        FBinWrite/F=3/B=3 refNum, y1
1895        FBinWrite/F=3/B=3 refNum, y2
1896        //move to the end of the file before closing
1897        FStatus refnum
1898        FSetPos refnum,V_logEOF
1899        Close refnum
1900       
1901        return(0)
1902End
1903
1904//associated file suffix is the first 4 characters of a text field starting
1905// at byte 404
1906// suffix must be four characters long, if not, it's truncated
1907//
1908Function WriteAssocFileSuffixToHeader(fname,suffix)
1909        String fname,suffix
1910               
1911        suffix = suffix[0,3]            //limit to 4 characters
1912        WriteTextToHeader(fname,suffix,404)
1913       
1914        return(0)
1915end
1916
1917
1918// Jan 2008
1919// it has been determined that the true pixel dimension of the ordela detectors is not 5.0 mm
1920// but somewhat larger (5.08? mm). "new" data files will be written out with the proper size
1921// and old files will be patched batchwise to put the prpoer value in the header
1922
1923Proc PatchDetectorPixelSize(firstFile,lastFile,XSize,YSize)
1924        Variable firstFile=1,lastFile=100,XSize=5.08,YSize=5.08
1925
1926        fPatchDetectorPixelSize(firstFile,lastFile,XSize,YSize)
1927
1928End
1929
1930Proc ReadDetectorPixelSize(firstFile,lastFile)
1931        Variable firstFile=1,lastFile=100
1932       
1933        fReadDetectorPixelSize(firstFile,lastFile)
1934End
1935
1936// simple utility to patch the detector pixel size in the file headers
1937// pass in the dimensions in mm
1938// lo is the first file number
1939// hi is the last file number (inclusive)
1940//
1941Function fPatchDetectorPixelSize(lo,hi,xdim,ydim)
1942        Variable lo,hi,xdim,ydim
1943       
1944        Variable ii
1945        String file
1946       
1947        //loop over all files
1948        for(ii=lo;ii<=hi;ii+=1)
1949                file = FindFileFromRunNumber(ii)
1950                if(strlen(file) != 0)
1951                        WriteDetPixelXToHeader(file,xdim)
1952                        WriteDetPixelyToHeader(file,ydim)
1953                else
1954                        printf "run number %d not found\r",ii
1955                endif
1956        endfor
1957       
1958        return(0)
1959End
1960
1961// simple utility to read the pixel size stored in the file header
1962Function fReadDetectorPixelSize(lo,hi)
1963        Variable lo,hi
1964       
1965        String file
1966        Variable xdim,ydim,ii
1967       
1968        for(ii=lo;ii<=hi;ii+=1)
1969                file = FindFileFromRunNumber(ii)
1970                if(strlen(file) != 0)
1971                        xdim = getDetectorPixelXSize(file)
1972                        ydim = getDetectorPixelYSize(file)
1973                        printf "File %d:  Pixel dimensions (mm): X = %g\t Y = %g\r",ii,xdim,ydim
1974                else
1975                        printf "run number %d not found\r",ii
1976                endif
1977        endfor
1978       
1979        return(0)
1980End
1981
1982
1983
1984//*******************
1985//************
1986// simple command - line utilities to convert/unconvert the header value
1987// that flags files as using lenses
1988//
1989// stored in reals[28], header byte start @ 300
1990//
1991// currently, two values (0 | 1) = (no lens | yes lens)
1992// ideally, this field will have the actual number of lenses inserted.
1993//
1994// this is used in getResolution (reads the reals[]) and switches the calculation
1995//************
1996
1997Proc ConvertToLens(RunNumber)
1998        Variable RunNumber
1999        HeaderToLensResolution(RunNumber)
2000End
2001
2002Proc ConvertToPinhole(RunNumber)
2003        Variable RunNumber
2004        HeaderToPinholeResolution(RunNumber)
2005End
2006
2007// sets the flag to zero in the file (= 0)
2008Function HeaderToPinholeResolution(num)
2009        Variable num   
2010       
2011        //Print "UnConvert"
2012        String fullname=""
2013       
2014        fullname = FindFileFromRunNumber(num)
2015        Print fullname
2016        //report error or change the file
2017        if(cmpstr(fullname,"")==0)
2018                Print "HeaderToPinhole - file not found"
2019        else
2020                //Print "Unconvert",fullname
2021                WriteVAXReal(fullname,0,300)
2022        Endif
2023        return(0)
2024End
2025
2026// sets the flag to one in the file (= 1)
2027Function HeaderToLensResolution(num)
2028        Variable num   
2029       
2030        //Print "UnConvert"
2031        String fullname=""
2032       
2033        fullname = FindFileFromRunNumber(num)
2034        Print fullname
2035        //report error or change the file
2036        if(cmpstr(fullname,"")==0)
2037                Print "HeaderToPinhole - file not found"
2038        else
2039                //Print "Unconvert",fullname
2040                WriteVAXReal(fullname,1,300)
2041        Endif
2042        return(0)
2043End
2044
2045
2046////// OCT 2009, facility specific bits from MonteCarlo functions()
2047//"type" is the data folder that has the data array that is to be (re)written as a full
2048// data file, as if it was a raw data file
2049//
2050Function/S Write_RawData_File(type,fullpath,dialog)
2051        String type,fullpath
2052        Variable dialog         //=1 will present dialog for name
2053
2054        String filename = ""
2055        filename = Write_VAXRaw_Data(type,fullpath,dialog)
2056       
2057        return(filename)
2058End
2059
2060// given a data folder, write out the corresponding VAX binary data file.
2061//
2062// I don't think that I can generate a STRUCT and then lay that down - since the
2063// VAX FP format has to be duplicated with a write/read/flip/re-write dance...
2064//
2065// seems to work correctly byte for byte
2066// compression has been implmented also, for complete replication of the format (n>32767 in a cell)
2067//
2068// SRK 29JAN09
2069//
2070// other functions needed:
2071//
2072//
2073// one to generate a fake data file name, and put the matching name in the data header
2074// !! must fake the Annn suffix too! this is used...
2075// use a prefix, keep a run number, initials SIM, and alpha as before (start randomly, don't bother changing?)
2076//
2077// for right now, keep a run number, and generate
2078// PREFIXnnn.SA2_SIM_Annn
2079// also, start the index @ 100 to avoid leading zeros (although I have the functions available)
2080
2081// one to generate the date/time string in VAX format, right # characters// Print Secs2Time(DateTime,3)                         // Prints 13:07:29
2082// Print Secs2Time(DateTime,3)                          // Prints 13:07:29
2083//      Print Secs2Date(DateTime,-2)            // 1993-03-14                   //this call is independent of System date/time!//
2084//
2085//
2086// simulation should call as ("SAS","",0) to bypass the dialog, and to fill the header
2087// this could be modified in the future to be more generic
2088//
2089///
2090// changed to return the string w/ the filename as written for later use
2091Function/S Write_VAXRaw_Data(type,fullpath,dialog)
2092        String type,fullpath
2093        Variable dialog         //=1 will present dialog for name
2094       
2095        String destStr=""
2096        Variable refNum,ii,val,err
2097       
2098       
2099        destStr = "root:Packages:NIST:"+type
2100       
2101        SetDataFolder $destStr
2102        WAVE intw=integersRead
2103        WAVE rw=realsRead
2104        WAVE/T textw=textRead
2105       
2106        WAVE linear_data = linear_data
2107        Duplicate/O linear_data tmp_data
2108               
2109        NVAR/Z rawCts = root:Packages:NIST:SAS:gRawCounts
2110        if(cmpstr("SAS",type)==0 && !rawCts)            //simulation data, and is not RAW counts, so scale it back
2111
2112                //use kappa to get back to counts => linear_data = round(linear_data*kappa)
2113                String strNote = note(linear_data)
2114                Variable kappa = NumberByKey("KAPPA", strNote , "=", ";")
2115                NVAR detectorEff = root:Packages:NIST:SAS:g_detectorEff
2116
2117                tmp_data *= kappa
2118                tmp_data *= detectorEff
2119//              Print kappa, detectorEff
2120                Redimension/I tmp_data
2121        endif
2122       
2123        WAVE w=tmp_data
2124
2125        // check for data values that are too large. the maximum VAX compressed data value is 2767000
2126        //
2127        WaveStats/Q w
2128        if(V_max > 2767000)
2129                Abort "Some individual pixel values are > 2767000 and the data can't be saved in VAX format"
2130        Endif
2131       
2132        //check each wave
2133        If(!(WaveExists(intw)))
2134                Abort "intw DNExist WriteVAXData()"
2135        Endif
2136        If(!(WaveExists(rw)))
2137                Abort "rw DNExist WriteVAXData()"
2138        Endif
2139        If(!(WaveExists(textw)))
2140                Abort "textw DNExist WriteVAXData()"
2141        Endif
2142        If(!(WaveExists(w)))
2143                Abort "linear_data DNExist WriteVAXData()"
2144        Endif
2145       
2146       
2147//      if(dialog)
2148//              PathInfo/S catPathName
2149//              fullPath = DoSaveFileDialog("Save data as")
2150//              If(cmpstr(fullPath,"")==0)
2151//                      //user cancel, don't write out a file
2152//                      Close/A
2153//                      Abort "no data file was written"
2154//              Endif
2155//              //Print "dialog fullpath = ",fullpath
2156//      Endif
2157       
2158        // save to home, or get out
2159        //
2160        PathInfo home
2161        if(V_flag       == 0)
2162                Abort "no save path defined. Save the experiment to generate a home path"
2163        endif
2164       
2165        fullPath = S_path               //not the full path yet, still need the name, after the header is filled
2166       
2167       
2168        Make/O/B/U/N=33316 tmpFile              //unsigned integers for a blank data file
2169        tmpFile=0
2170       
2171//      Make/O/W/N=16401 dataWRecMarkers                        // don't convert to 16 bit here, rather write to file as 16 bit later
2172        Make/O/I/N=16401 dataWRecMarkers
2173        AddRecordMarkers(w,dataWRecMarkers)
2174               
2175        // need to re-compress?? maybe never a problem, but should be done for the odd case
2176        dataWRecMarkers = CompressI4toI2(dataWRecMarkers)               //unless a pixel value is > 32767, the same values are returned
2177       
2178        // fill the last bits of the header information
2179        err = SimulationVAXHeader(type)         //if the type != 'SAS', this function does nothing
2180       
2181        if (err == -1)
2182                Abort "no sample label entered - no file written"                       // User did not fill in header correctly/completely
2183        endif
2184        fullPath = fullPath + textW[0]
2185       
2186        // lay down a blank file
2187        Open refNum as fullpath
2188                FBinWrite refNum,tmpFile                        //file is the right size, but all zeroes
2189        Close refNum
2190       
2191        // fill up the header
2192        // text values
2193        // elements of textW are already the correct length set by the read, but just make sure
2194        String str
2195       
2196        if(strlen(textw[0])>21)
2197                textw[0] = (textw[0])[0,20]
2198        endif
2199        if(strlen(textw[1])>20)
2200                textw[1] = (textw[1])[0,19]
2201        endif
2202        if(strlen(textw[2])>3)
2203                textw[2] = (textw[2])[0,2]
2204        endif
2205        if(strlen(textw[3])>11)
2206                textw[3] = (textw[3])[0,10]
2207        endif
2208        if(strlen(textw[4])>1)
2209                textw[4] = (textw[4])[0]
2210        endif
2211        if(strlen(textw[5])>8)
2212                textw[5] = (textw[5])[0,7]
2213        endif
2214        if(strlen(textw[6])>60)
2215                textw[6] = (textw[6])[0,59]
2216        endif
2217        if(strlen(textw[7])>6)
2218                textw[7] = (textw[7])[0,5]
2219        endif
2220        if(strlen(textw[8])>6)
2221                textw[8] = (textw[8])[0,5]
2222        endif
2223        if(strlen(textw[9])>6)
2224                textw[9] = (textw[9])[0,5]
2225        endif
2226        if(strlen(textw[10])>42)
2227                textw[10] = (textw[10])[0,41]
2228        endif   
2229       
2230        ii=0
2231        Open/A/T="????TEXT" refnum as fullpath      //Open for writing! Move to EOF before closing!
2232                str = textW[ii]
2233                FSetPos refnum,2                                                        ////file name
2234                FBinWrite/F=0 refnum, str      //native object format (character)
2235                ii+=1
2236                str = textW[ii]
2237                FSetPos refnum,55                                                       ////date/time
2238                FBinWrite/F=0 refnum, str
2239                ii+=1
2240                str = textW[ii]
2241                FSetPos refnum,75                                                       ////type
2242                FBinWrite/F=0 refnum, str
2243                ii+=1
2244                str = textW[ii]
2245                FSetPos refnum,78                                               ////def dir
2246                FBinWrite/F=0 refnum, str
2247                ii+=1
2248                str = textW[ii]
2249                FSetPos refnum,89                                               ////mode
2250                FBinWrite/F=0 refnum, str
2251                ii+=1
2252                str = textW[ii]
2253                FSetPos refnum,90                                               ////reserve
2254                FBinWrite/F=0 refnum, str
2255                ii+=1
2256                str = textW[ii]
2257                FSetPos refnum,98                                               ////@98, sample label
2258                FBinWrite/F=0 refnum, str
2259                ii+=1
2260                str = textW[ii]
2261                FSetPos refnum,202                                              //// T units
2262                FBinWrite/F=0 refnum, str
2263                ii+=1
2264                str = textW[ii]
2265                FSetPos refnum,208                                              //// F units
2266                FBinWrite/F=0 refnum, str
2267                ii+=1
2268                str = textW[ii]
2269                FSetPos refnum,214                                              ////det type
2270                FBinWrite/F=0 refnum, str
2271                ii+=1
2272                str = textW[ii]
2273                FSetPos refnum,404                                              ////reserve
2274                FBinWrite/F=0 refnum, str
2275       
2276                //move to the end of the file before closing
2277                FStatus refnum
2278                FSetPos refnum,V_logEOF
2279        Close refnum
2280       
2281       
2282        // integer values (4 bytes)
2283        ii=0
2284        Open/A/T="????TEXT" refnum as fullpath      //Open for writing! Move to EOF before closing!
2285                val = intw[ii]
2286                FSetPos refnum,23                                                       //nprefactors
2287                FBinWrite/B=3/F=3 refnum, val      //write a 4-byte integer
2288                ii+=1
2289                val=intw[ii]
2290                FSetPos refnum,27                                                       //ctime
2291                FBinWrite/B=3/F=3 refnum, val
2292                ii+=1
2293                val=intw[ii]
2294                FSetPos refnum,31                                                       //rtime
2295                FBinWrite/B=3/F=3 refnum, val
2296                ii+=1
2297                val=intw[ii]
2298                FSetPos refnum,35                                                       //numruns
2299                FBinWrite/B=3/F=3 refnum, val
2300                ii+=1
2301                val=intw[ii]
2302                FSetPos refnum,174                                                      //table
2303                FBinWrite/B=3/F=3 refnum, val
2304                ii+=1
2305                val=intw[ii]
2306                FSetPos refnum,178                                                      //holder
2307                FBinWrite/B=3/F=3 refnum, val
2308                ii+=1
2309                val=intw[ii]
2310                FSetPos refnum,182                                                      //blank
2311                FBinWrite/B=3/F=3 refnum, val
2312                ii+=1
2313                val=intw[ii]
2314                FSetPos refnum,194                                                      //tctrlr
2315                FBinWrite/B=3/F=3 refnum, val
2316                ii+=1
2317                val=intw[ii]
2318                FSetPos refnum,198                                                      //magnet
2319                FBinWrite/B=3/F=3 refnum, val
2320                ii+=1
2321                val=intw[ii]
2322                FSetPos refnum,244                                                      //det num
2323                FBinWrite/B=3/F=3 refnum, val
2324                ii+=1
2325                val=intw[ii]
2326                FSetPos refnum,248                                                      //det spacer
2327                FBinWrite/B=3/F=3 refnum, val
2328                ii+=1
2329                val=intw[ii]
2330                FSetPos refnum,308                                                      //tslice mult
2331                FBinWrite/B=3/F=3 refnum, val
2332                ii+=1
2333                val=intw[ii]
2334                FSetPos refnum,312                                                      //tsclice ltslice
2335                FBinWrite/B=3/F=3 refnum, val
2336                ii+=1
2337                val=intw[ii]
2338                FSetPos refnum,332                                                      //extra
2339                FBinWrite/B=3/F=3 refnum, val
2340                ii+=1
2341                val=intw[ii]
2342                FSetPos refnum,336                                                      //reserve
2343                FBinWrite/B=3/F=3 refnum, val
2344                ii+=1
2345                val=intw[ii]
2346                FSetPos refnum,376                                                      //blank1
2347                FBinWrite/B=3/F=3 refnum, val
2348                ii+=1
2349                val=intw[ii]
2350                FSetPos refnum,380                                                      //blank2
2351                FBinWrite/B=3/F=3 refnum, val
2352                ii+=1
2353                val=intw[ii]
2354                FSetPos refnum,384                                                      //blank3
2355                FBinWrite/B=3/F=3 refnum, val
2356                ii+=1
2357                val=intw[ii]
2358                FSetPos refnum,458                                                      //spacer
2359                FBinWrite/B=3/F=3 refnum, val
2360                ii+=1
2361                val=intw[ii]
2362                FSetPos refnum,478                                                      //box x1
2363                FBinWrite/B=3/F=3 refnum, val
2364                ii+=1
2365                val=intw[ii]
2366                FSetPos refnum,482                                                      //box x2
2367                FBinWrite/B=3/F=3 refnum, val
2368                ii+=1
2369                val=intw[ii]
2370                FSetPos refnum,486                                                      //box y1
2371                FBinWrite/B=3/F=3 refnum, val
2372                ii+=1
2373                val=intw[ii]
2374                FSetPos refnum,490                                                      //box y2
2375                FBinWrite/B=3/F=3 refnum, val
2376               
2377                //move to the end of the file before closing
2378                FStatus refnum
2379                FSetPos refnum,V_logEOF
2380        Close refnum
2381       
2382               
2383        //VAX 4-byte FP values. No choice here but to write/read/re-write to get
2384        // the proper format. there are 52! values to write
2385        //WriteVAXReal(fullpath,rw[n],start)
2386        // [0]
2387        WriteVAXReal(fullpath,rw[0],39)
2388        WriteVAXReal(fullpath,rw[1],43)
2389        WriteVAXReal(fullpath,rw[2],47)
2390        WriteVAXReal(fullpath,rw[3],51)
2391        WriteVAXReal(fullpath,rw[4],158)
2392        WriteVAXReal(fullpath,rw[5],162)
2393        WriteVAXReal(fullpath,rw[6],166)
2394        WriteVAXReal(fullpath,rw[7],170)
2395        WriteVAXReal(fullpath,rw[8],186)
2396        WriteVAXReal(fullpath,rw[9],190)
2397        // [10]
2398        WriteVAXReal(fullpath,rw[10],220)
2399        WriteVAXReal(fullpath,rw[11],224)
2400        WriteVAXReal(fullpath,rw[12],228)
2401        WriteVAXReal(fullpath,rw[13],232)
2402        WriteVAXReal(fullpath,rw[14],236)
2403        WriteVAXReal(fullpath,rw[15],240)
2404        WriteVAXReal(fullpath,rw[16],252)
2405        WriteVAXReal(fullpath,rw[17],256)
2406        WriteVAXReal(fullpath,rw[18],260)
2407        WriteVAXReal(fullpath,rw[19],264)
2408        // [20]
2409        WriteVAXReal(fullpath,rw[20],268)
2410        WriteVAXReal(fullpath,rw[21],272)
2411        WriteVAXReal(fullpath,rw[22],276)
2412        WriteVAXReal(fullpath,rw[23],280)
2413        WriteVAXReal(fullpath,rw[24],284)
2414        WriteVAXReal(fullpath,rw[25],288)
2415        WriteVAXReal(fullpath,rw[26],292)
2416        WriteVAXReal(fullpath,rw[27],296)
2417        WriteVAXReal(fullpath,rw[28],300)
2418        WriteVAXReal(fullpath,rw[29],320)
2419        // [30]
2420        WriteVAXReal(fullpath,rw[30],324)
2421        WriteVAXReal(fullpath,rw[31],328)
2422        WriteVAXReal(fullpath,rw[32],348)
2423        WriteVAXReal(fullpath,rw[33],352)
2424        WriteVAXReal(fullpath,rw[34],356)
2425        WriteVAXReal(fullpath,rw[35],360)
2426        WriteVAXReal(fullpath,rw[36],364)
2427        WriteVAXReal(fullpath,rw[37],368)
2428        WriteVAXReal(fullpath,rw[38],372)
2429        WriteVAXReal(fullpath,rw[39],388)
2430        // [40]
2431        WriteVAXReal(fullpath,rw[40],392)
2432        WriteVAXReal(fullpath,rw[41],396)
2433        WriteVAXReal(fullpath,rw[42],400)
2434        WriteVAXReal(fullpath,rw[43],450)
2435        WriteVAXReal(fullpath,rw[44],454)
2436        WriteVAXReal(fullpath,rw[45],470)
2437        WriteVAXReal(fullpath,rw[46],474)
2438        WriteVAXReal(fullpath,rw[47],494)
2439        WriteVAXReal(fullpath,rw[48],498)
2440        WriteVAXReal(fullpath,rw[49],502)
2441        // [50]
2442        WriteVAXReal(fullpath,rw[50],506)
2443        WriteVAXReal(fullpath,rw[51],510)
2444       
2445       
2446        // write out the data
2447        Open refNum as fullpath
2448                FSetPos refnum,514                                      //  OK
2449                FBinWrite/F=2/B=3 refNum,dataWRecMarkers                //don't trust the native format
2450                FStatus refNum
2451                FSetPos refNum,V_logEOF
2452        Close refNum
2453       
2454        // all done
2455        Killwaves/Z tmpFile,dataWRecMarkers,tmp_data
2456       
2457        Print "Saved VAX binary data as:  ",textW[0]
2458        SetDatafolder root:
2459        return(fullpath)
2460End
2461
2462
2463Function AddRecordMarkers(in,out)
2464        Wave in,out
2465       
2466        Variable skip,ii
2467
2468//      Duplicate/O in,out
2469//      Redimension/N=16401 out
2470
2471        out=0
2472       
2473        ii=0
2474        skip=0
2475        out[ii] = 1
2476        ii+=1
2477        do
2478                if(mod(ii+skip,1022)==0)
2479                        out[ii+skip] = 0                //999999
2480                        skip+=1                 //increment AFTER filling the current marker
2481                endif
2482                out[ii+skip] = in[ii-1]
2483                ii+=1
2484        while(ii<=16384)
2485       
2486       
2487        return(0)
2488End
2489
2490
2491
2492
2493//        INTEGER*2 FUNCTION I4ToI2(I4)
2494//C
2495//C       Original author : Jim Rhyne
2496//C       Modified by     : Frank Chen 09/26/90
2497//C
2498//C       I4ToI2 = I4,                            I4 in [0,32767]
2499//C       I4ToI2 = -777,                          I4 in (2767000,...)
2500//C       I4ToI2 mapped to -13277 to -32768,      otherwise
2501//C
2502//C       the mapped values [-776,-1] and [-13276,-778] are not used
2503//C
2504//C       I4max should be 2768499, this value will maps to -32768
2505//C       and mantissa should be compared  using
2506//C               IF (R4 .GE. IPW)
2507//C       instead of
2508//C               IF (R4 .GT. (IPW - 1.0))
2509//C
2510//
2511//
2512//C       I4      :       input I*4
2513//C       R4      :       temperory real number storage
2514//C       IPW     :       IPW = IB ** ND
2515//C       NPW     :       number of power
2516//C       IB      :       Base value
2517//C       ND      :       Number of precision digits
2518//C       I4max   :       max data value w/ some error
2519//C       I2max   :       max data value w/o error
2520//C       Error   :       when data value > I4max
2521//C
2522//        INTEGER*4       I4
2523//        INTEGER*4       NPW
2524//        REAL*4          R4
2525//        INTEGER*4       IPW
2526//        INTEGER*4       IB      /10/
2527//        INTEGER*4       ND      /4/
2528//        INTEGER*4       I4max   /2767000/
2529//        INTEGER*4       I2max   /32767/
2530//        INTEGER*4       Error   /-777/
2531//
2532Function CompressI4toI2(i4)
2533        Variable i4
2534
2535        Variable npw,ipw,ib,nd,i4max,i2max,error,i4toi2
2536        Variable r4
2537       
2538        ib=10
2539        nd=4
2540        i4max=2767000
2541        i2max=32767
2542        error=-777
2543       
2544        if(i4 <= i4max)
2545                r4=i4
2546                if(r4 > i2max)
2547                        ipw = ib^nd
2548                        npw=0
2549                        do
2550                                if( !(r4 > (ipw-1)) )           //to simulate a do-while loop evaluating at top
2551                                        break
2552                                endif
2553                                npw=npw+1
2554                                r4=r4/ib               
2555                        while (1)
2556                        i4toi2 = -1*trunc(r4+ipw*npw)
2557                else
2558                        i4toi2 = trunc(r4)              //shouldn't I just return i4 (as a 2 byte value?)
2559                endif
2560        else
2561                i4toi2=error
2562        endif
2563        return(i4toi2)
2564End
2565
2566
2567// function to fill the extra bits of header information to make a "complete"
2568// simulated VAX data file.
2569//
2570// NCNR-Specific. is hard wired to the SAS folder. If saving from any other folder, set all of the header
2571// information before saving, and pass a null string to this procedure to bypass it entirely
2572//
2573Function SimulationVAXHeader(folder)
2574        String folder
2575
2576        if(cmpstr(folder,"SAS")!=0)             //if not the SAS folder passed in, get out now, and return 1 (-1 is the error condition)
2577                return(1)
2578        endif
2579       
2580        Wave rw=root:Packages:NIST:SAS:realsRead
2581        Wave iw=root:Packages:NIST:SAS:integersRead
2582        Wave/T tw=root:Packages:NIST:SAS:textRead
2583        Wave res=root:Packages:NIST:SAS:results
2584       
2585// integers needed:
2586        //[2] count time
2587        NVAR ctTime = root:Packages:NIST:SAS:gCntTime
2588        iw[2] = ctTime
2589       
2590//reals are partially set in SASCALC initializtion
2591        //remaining values are updated automatically as SASCALC is modified
2592        // -- but still need:
2593        //      [0] monitor count
2594        //      [2] detector count (w/o beamstop)
2595        //      [4] transmission
2596        //      [5] thickness (in cm)
2597        NVAR imon = root:Packages:NIST:SAS:gImon
2598        rw[0] = imon
2599        rw[2] = res[9]
2600        rw[4] = res[8]
2601        NVAR thick = root:Packages:NIST:SAS:gThick
2602        rw[5] = thick
2603       
2604// text values needed:
2605// be sure they are padded to the correct length
2606        // [0] filename (do I fake a VAX name? probably yes...)
2607        // [1] date/time in VAX format
2608        // [2] type (use SIM)
2609        // [3] def dir (use [NG7SANS99])
2610        // [4] mode? C
2611        // [5] reserve (another date), prob not needed
2612        // [6] sample label
2613        // [9] det type "ORNL  " (6 chars)
2614
2615        SVAR gInstStr = root:Packages:NIST:SAS:gInstStr
2616               
2617        tw[1] = Secs2Date(DateTime,-2)+"  "+ Secs2Time(DateTime,3)              //20 chars, not quite VAX format
2618        tw[2] = "SIM"
2619        tw[3] = "["+gInstStr+"SANS99]"
2620        tw[4] = "C"
2621        tw[5] = "01JAN09 "
2622        tw[9] = "ORNL  "
2623       
2624       
2625        //get the run index and the sample label from the optional parameters, or from a dialog
2626        NVAR index = root:Packages:NIST:SAS:gSaveIndex
2627        SVAR prefix = root:Packages:NIST:SAS:gSavePrefix
2628// did the user pass in values?
2629        NVAR autoSaveIndex = root:Packages:NIST:SAS:gAutoSaveIndex
2630        SVAR autoSaveLabel = root:Packages:NIST:SAS:gAutoSaveLabel
2631       
2632        String labelStr=""     
2633        Variable runNum
2634        if( (autoSaveIndex != 0) && (strlen(autoSaveLabel) > 0) )
2635                // all is OK, proceed with the save
2636                labelStr = autoSaveLabel
2637                runNum = autoSaveIndex          //user must take care of incrementing this!
2638        else
2639                //one or the other, or both are missing, so ask
2640                runNum = index
2641                Prompt labelStr, "Enter sample label "          // Set prompt for x param
2642                Prompt runNum,"Run Number (automatically increments)"
2643                DoPrompt "Enter sample label", labelStr,runNum
2644                if (V_Flag)
2645                        //Print "no sample label entered - no file written"
2646                        //index -=1
2647                        return -1                                                               // User canceled
2648                endif
2649                if(runNum != index)
2650                        index = runNum
2651                endif
2652                index += 1
2653        endif
2654       
2655
2656
2657        //make a three character string of the run number
2658        String numStr=""
2659        if(runNum<10)
2660                numStr = "00"+num2str(runNum)
2661        else
2662                if(runNum<100)
2663                        numStr = "0"+num2str(runNum)
2664                else
2665                        numStr = num2str(runNum)
2666                Endif
2667        Endif
2668        //date()[0] is the first letter of the day of the week
2669        // OK for most cases, except for an overnight simulation! then the suffix won't sort right...
2670//      tw[0] = prefix+numstr+".SA2_SIM_"+(date()[0])+numStr
2671
2672//fancier, JAN=A, FEB=B, etc...
2673        String timeStr= secs2date(datetime,-1)
2674        String monthStr=StringFromList(1, timeStr  ,"/")
2675
2676        tw[0] = prefix+numstr+".SA2_SIM_"+(num2char(str2num(monthStr)+64))+numStr
2677       
2678        labelStr = PadString(labelStr,60,0x20)  //60 fortran-style spaces
2679        tw[6] = labelStr[0,59]
2680       
2681        return(0)
2682End
2683
2684Function ExamineHeader(type)
2685        String type
2686
2687        String data_folder = type
2688        String dataPath = "root:Packages:NIST:"+data_folder
2689        String cur_folder = "ExamineHeader"
2690        String curPath = "root:Packages:NIST:"+cur_folder
2691       
2692        //SetDataFolder curPath
2693
2694        Wave intw=$(dataPath+":IntegersRead")
2695        Wave realw=$(dataPath+":RealsRead")
2696        Wave/T textw=$(dataPath+":TextRead")
2697        Wave logw=$(dataPath+":LogicalsRead")
2698
2699
2700        print "----------------------------------"
2701        print "Header Details"
2702        print "----------------------------------"
2703        print "fname :\t\t"+textw[0]
2704        //
2705        print "run.npre :\t\t"+num2str(intw[0])
2706        print "run.ctime :\t\t"+num2str(intw[1])
2707        print "run.rtime :\t\t"+num2str(intw[2])
2708        print "run.numruns :\t\t"+num2str(intw[3])
2709        //
2710        print "run.moncnt :\t\t"+num2str(realw[0])
2711        print "run.savmon :\t\t"+num2str(realw[1])
2712        print "run.detcnt :\t\t"+num2str(realw[2])
2713        print "run.atten :\t\t"+num2str(realw[3])       
2714        //
2715        print "run.timdat:\t\t"+textw[1]
2716        print "run.type:\t\t"+textw[2]
2717        print "run.defdir:\t\t"+textw[3]
2718        print "run.mode:\t\t"+textw[4]
2719        print "run.reserve:\t\t"+textw[5]
2720        print "sample.labl:\t\t"+textw[6]
2721        //
2722        print "sample.trns:\t\t"+num2str(realw[4])
2723        print "sample.thk:\t\t"+num2str(realw[5])
2724        print "sample.position:\t\t"+num2str(realw[6])
2725        print "sample.rotang:\t\t"+num2str(realw[7])
2726        //
2727        print "sample.table:\t\t"+num2str(intw[4])
2728        print "sample.holder:\t\t"+num2str(intw[5])
2729        print "sample.blank:\t\t"+num2str(intw[6])
2730        //
2731        print "sample.temp:\t\t"+num2str(realw[8])
2732        print "sample.field:\t\t"+num2str(realw[9])     
2733        //
2734        print "sample.tctrlr:\t\t"+num2str(intw[7])
2735        print "sample.magnet:\t\t"+num2str(intw[8])
2736        //
2737        print "sample.tunits:\t\t"+textw[7]
2738        print "sample.funits:\t\t"+textw[8]
2739        print "det.typ:\t\t"+textw[9]
2740        //
2741        print "det.calx(1):\t\t"+num2str(realw[10])
2742        print "det.calx(2):\t\t"+num2str(realw[11])
2743        print "det.calx(3):\t\t"+num2str(realw[12])
2744        print "det.caly(1):\t\t"+num2str(realw[13])
2745        print "det.caly(2):\t\t"+num2str(realw[14])
2746        print "det.caly(3):\t\t"+num2str(realw[15])
2747        //
2748        print "det.num:\t\t"+num2str(intw[9])
2749        print "det.spacer:\t\t"+num2str(intw[10])
2750        //
2751        print "det.beamx:\t\t"+num2str(realw[16])
2752        print "det.beamy:\t\t"+num2str(realw[17])
2753        print "det.dis:\t\t"+num2str(realw[18])
2754        print "det.offset:\t\t"+num2str(realw[19])
2755        print "det.siz:\t\t"+num2str(realw[20])
2756        print "det.bstop:\t\t"+num2str(realw[21])
2757        print "det.blank:\t\t"+num2str(realw[22])
2758        print "resolution.ap1:\t\t"+num2str(realw[23])
2759        print "resolution.ap2:\t\t"+num2str(realw[24])
2760        print "resolution.ap12dis:\t\t"+num2str(realw[25])
2761        print "resolution.lmda:\t\t"+num2str(realw[26])
2762        print "resolution.dlmda:\t\t"+num2str(realw[27])
2763        print "resolution.nlenses:\t\t"+num2str(realw[28])     
2764        //
2765        print "tslice.slicing:\t\t"+num2str(logw[0])
2766        //
2767        print "tslice.multfact:\t\t"+num2str(intw[11])
2768        print "tslice.ltslice:\t\t"+num2str(intw[12])
2769        //
2770        print "temp.printemp:\t\t"+num2str(logw[1])
2771        //
2772        print "temp.hold:\t\t"+num2str(realw[29])
2773        print "temp.err:\t\t"+num2str(realw[30])
2774        print "temp.blank:\t\t"+num2str(realw[31])
2775        //
2776        print "temp.extra:\t\t"+num2str(intw[13])
2777        print "temp.err:\t\t"+num2str(intw[14])
2778        //
2779        print "magnet.printmag:\t\t"+num2str(logw[2])
2780        print "magnet.sensor:\t\t"+num2str(logw[3])
2781        //
2782        print "magnet.current:\t\t"+num2str(realw[32])
2783        print "magnet.conv:\t\t"+num2str(realw[33])
2784        print "magnet.fieldlast:\t\t"+num2str(realw[34])
2785        print "magnet.blank:\t\t"+num2str(realw[35])
2786        print "magnet.spacer:\t\t"+num2str(realw[36])
2787        print "bmstp.xpos:\t\t"+num2str(realw[37])
2788        print "bmstop.ypos:\t\t"+num2str(realw[38])
2789        //     
2790        print "params.blank1:\t\t"+num2str(intw[15])
2791        print "params.blank2:\t\t"+num2str(intw[16])
2792        print "params.blank3:\t\t"+num2str(intw[17])
2793        //
2794        print "params.trnscnt:\t\t"+num2str(realw[39])
2795        print "params.extra1:\t\t"+num2str(realw[40])
2796        print "params.extra2:\t\t"+num2str(realw[41])
2797        print "params.extra3:\t\t"+num2str(realw[42])
2798        //     
2799        print "params.reserve:\t\t"+textw[10]
2800        //
2801        print "voltage.printemp:\t\t"+num2str(logw[4])
2802        //
2803        print "voltage.volts:\t\t"+num2str(realw[43])
2804        print "voltage.blank:\t\t"+num2str(realw[44])
2805        //     
2806        print "voltage.spacer:\t\t"+num2str(intw[18])
2807        //
2808        print "polarization.printpol:\t\t"+num2str(logw[5])
2809        print "polarization.flipper:\t\t"+num2str(logw[6])
2810        //     
2811        print "polarization.horiz:\t\t"+num2str(realw[45])
2812        print "polarization.vert:\t\t"+num2str(realw[46])
2813        //
2814        print "analysis.rows(1):\t\t"+num2str(intw[19])
2815        print "analysis.rows(2):\t\t"+num2str(intw[20])
2816        print "analysis.cols(1):\t\t"+num2str(intw[21])
2817        print "analysis.cols(2):\t\t"+num2str(intw[22])
2818        //
2819        print "analysis.factor:\t\t"+num2str(realw[47])
2820        print "analysis.qmin:\t\t"+num2str(realw[48])
2821        print "analysis.qmax:\t\t"+num2str(realw[49])
2822        print "analysis.imin:\t\t"+num2str(realw[50])
2823        print "analysis.imax:\t\t"+num2str(realw[51])
2824
2825End
2826
2827
2828// Sept 2009 -SRK
2829// the ICE instrument control software is not correctly writing out the file name to the header in the specific
2830// case of a file prefix less than 5 characters. ICE is quite naturally putting the blanke space(s) at the end of
2831// the string. However, the VAX puts them at the beginning...
2832Proc PatchFileNameInHeader(firstFile,lastFile)
2833        Variable firstFile=1,lastFile=100
2834
2835        fPatchFileName(firstFile,lastFile)
2836
2837End
2838
2839Proc ReadFileNameInHeader(firstFile,lastFile)
2840        Variable firstFile=1,lastFile=100
2841       
2842        fReadFileName(firstFile,lastFile)
2843End
2844
2845
2846// simple utility to patch the file name in the file headers
2847// lo is the first file number
2848// hi is the last file number (inclusive)
2849//
2850// will read the 21 character file name and put any spaces at the front of the string
2851// like the VAX does. Should have absolutely no effect if there are spaces at the
2852// beginning of the string, as the VAX does.
2853Function fPatchFileName(lo,hi)
2854        Variable lo,hi
2855       
2856        Variable ii
2857        String file,fileName
2858       
2859        //loop over all files
2860        for(ii=lo;ii<=hi;ii+=1)
2861                file = FindFileFromRunNumber(ii)
2862                if(strlen(file) != 0)
2863                        fileName = getFileName(file)
2864                        WriteFileNameToHeader(file,fileName)
2865                else
2866                        printf "run number %d not found\r",ii
2867                endif
2868        endfor
2869       
2870        return(0)
2871End
2872
2873// simple utility to read the file name stored in the file header (and the suffix)
2874Function fReadFileName(lo,hi)
2875        Variable lo,hi
2876       
2877        String file,fileName,suffix
2878        Variable ii
2879       
2880        for(ii=lo;ii<=hi;ii+=1)
2881                file = FindFileFromRunNumber(ii)
2882                if(strlen(file) != 0)
2883                        fileName = getFileName(file)
2884                        suffix = getSuffix(file)
2885                        printf "File %d:  File name = %s\t\tSuffix = %s\r",ii,fileName,suffix
2886                else
2887                        printf "run number %d not found\r",ii
2888                endif
2889        endfor
2890       
2891        return(0)
2892End
2893
2894
2895
2896
2897// April 2009 - AJJ
2898// The new ICE instrument control software was not correctly writing the run.defdir field
2899// The format of that field should be [NGxSANSn] where x is 3 or 7 and nn is 0 through 50
2900
2901Proc PatchUserAccountName(firstFile,lastFile,acctName)
2902        Variable firstFile=1,lastFile=100
2903        String acctName = "NG3SANS0"
2904
2905        fPatchUserAccountName(firstFile,lastFile,acctName)
2906
2907End
2908
2909Proc ReadUserAccountName(firstFile,lastFile)
2910        Variable firstFile=1,lastFile=100
2911       
2912        fReadUserAccountName(firstFile,lastFile)
2913End
2914
2915// simple utility to patch the user account name in the file headers
2916// pass in the account name as a string
2917// lo is the first file number
2918// hi is the last file number (inclusive)
2919//
2920Function fPatchUserAccountName(lo,hi,acctName)
2921        Variable lo,hi
2922        String acctName
2923       
2924        Variable ii
2925        String file
2926       
2927        //loop over all files
2928        for(ii=lo;ii<=hi;ii+=1)
2929                file = FindFileFromRunNumber(ii)
2930                if(strlen(file) != 0)
2931                        WriteAcctNameToHeader(file,acctName)
2932                else
2933                        printf "run number %d not found\r",ii
2934                endif
2935        endfor
2936       
2937        return(0)
2938End
2939
2940// simple utility to read the user account name stored in the file header
2941Function fReadUserAccountName(lo,hi)
2942        Variable lo,hi
2943       
2944        String file,acctName
2945        Variable ii
2946       
2947        for(ii=lo;ii<=hi;ii+=1)
2948                file = FindFileFromRunNumber(ii)
2949                if(strlen(file) != 0)
2950                        acctName = getAcctName(file)
2951                        printf "File %d:  Account name = %s\r",ii,acctName
2952                else
2953                        printf "run number %d not found\r",ii
2954                endif
2955        endfor
2956       
2957        return(0)
2958End
2959
2960// May 2009 - SRK
2961// Monitor count not written correctly to file from ICE
2962
2963Proc PatchMonitorCount(firstFile,lastFile,monCtRate)
2964        Variable firstFile=1,lastFile=100,monCtRate
2965
2966        fPatchMonitorCount(firstFile,lastFile,monCtRate)
2967
2968End
2969
2970Proc ReadMonitorCount(firstFile,lastFile)
2971        Variable firstFile=1,lastFile=100
2972       
2973        fReadMonitorCount(firstFile,lastFile)
2974End
2975
2976// simple utility to patch the user account name in the file headers
2977// pass in the account name as a string
2978// lo is the first file number
2979// hi is the last file number (inclusive)
2980//
2981Function fPatchMonitorCount(lo,hi,monCtRate)
2982        Variable lo,hi,monCtRate
2983       
2984        Variable ii,ctTime
2985        String file
2986       
2987        //loop over all files
2988        for(ii=lo;ii<=hi;ii+=1)
2989                file = FindFileFromRunNumber(ii)
2990                if(strlen(file) != 0)
2991                        ctTime = getCountTime(file)
2992                        WriteMonitorCountToHeader(file,ctTime*monCtRate)                       
2993                else
2994                        printf "run number %d not found\r",ii
2995                endif
2996        endfor
2997       
2998        return(0)
2999End
3000
3001// simple utility to read the user account name stored in the file header
3002Function fReadMonitorCount(lo,hi)
3003        Variable lo,hi
3004       
3005        String file
3006        Variable ii,monitorCount
3007       
3008        for(ii=lo;ii<=hi;ii+=1)
3009                file = FindFileFromRunNumber(ii)
3010                if(strlen(file) != 0)
3011                        monitorCount = getMonitorCount(file)
3012                        printf "File %d:  Monitor Count = %g\r",ii,monitorCount
3013                else
3014                        printf "run number %d not found\r",ii
3015                endif
3016        endfor
3017       
3018        return(0)
3019End
3020
3021
3022// May 2014 - SRK
3023// Detector Deadtime (possibly) written to file by ICE
3024
3025Proc PatchDetectorDeadtime(firstFile,lastFile,deadtime)
3026        Variable firstFile=1,lastFile=100,deadtime
3027
3028        fPatchDetectorDeadtime(firstFile,lastFile,deadtime)
3029
3030End
3031
3032Proc ReadDetectorDeadtime(firstFile,lastFile)
3033        Variable firstFile=1,lastFile=100
3034       
3035        fReadDetectorDeadtime(firstFile,lastFile)
3036End
3037
3038// simple utility to patch the detector deadtime in the file headers
3039// pass in the account name as a string
3040// lo is the first file number
3041// hi is the last file number (inclusive)
3042//
3043Function fPatchDetectorDeadtime(lo,hi,deadtime)
3044        Variable lo,hi,deadtime
3045       
3046        Variable ii
3047        String file
3048       
3049        //loop over all files
3050        for(ii=lo;ii<=hi;ii+=1)
3051                file = FindFileFromRunNumber(ii)
3052                if(strlen(file) != 0)
3053                        WriteDeadtimeToHeader(file,deadtime)                   
3054                else
3055                        printf "run number %d not found\r",ii
3056                endif
3057        endfor
3058       
3059        return(0)
3060End
3061
3062// simple utility to read the detector deadtime stored in the file header
3063Function fReadDetectorDeadtime(lo,hi)
3064        Variable lo,hi
3065       
3066        String file
3067        Variable ii,deadtime
3068       
3069        for(ii=lo;ii<=hi;ii+=1)
3070                file = FindFileFromRunNumber(ii)
3071                if(strlen(file) != 0)
3072                        deadtime = getDetectorDeadtime(file)
3073                        printf "File %d:  Detector Dead time (s) = %g\r",ii,deadtime
3074                else
3075                        printf "run number %d not found\r",ii
3076                endif
3077        endfor
3078       
3079        return(0)
3080End
3081
3082
3083
3084/////
3085Proc ReadDetectorCount(firstFile,lastFile)
3086        Variable firstFile=1,lastFile=100
3087       
3088        fReadDetectorCount(firstFile,lastFile)
3089End
3090
3091
3092// simple utility to read the detector count from the header, and the summed data value
3093// and print out the values
3094Function fReadDetectorCount(lo,hi)
3095        Variable lo,hi
3096       
3097        String file
3098        Variable ii,summed
3099       
3100        for(ii=lo;ii<=hi;ii+=1)
3101                file = FindFileFromRunNumber(ii)
3102                if(strlen(file) != 0)
3103                        ReadHeaderAndData(file)
3104                        Wave rw=root:Packages:NIST:RAW:RealsRead
3105                        Wave data=root:Packages:NIST:RAW:data                   //data as read in is linear
3106                        summed = sum(data,-inf,inf)
3107                        printf "File %d:  DetCt Header = %g\t Detector Sum = %g\t Ratio sum/hdr = %g\r",ii,rw[2],summed,summed/rw[2]
3108                else
3109                        printf "run number %d not found\r",ii
3110                endif
3111        endfor
3112       
3113        return(0)
3114End
3115
3116
3117////// OCT 2009, facility specific bits from ProDiv()
3118//"type" is the data folder that has the corrected, patched, and normalized DIV data array
3119//
3120// the header of this file is rather unimportant. Filling in a title at least would be helpful/
3121//
3122Function Write_DIV_File(type)
3123        String type
3124       
3125        // Your file writing function here. Don't try to duplicate the VAX binary format...
3126        WriteVAXWorkFile(type)
3127       
3128        return(0)
3129End
3130
3131//writes an VAX-style WORK file, "exactly" as it would be output from the VAX
3132//except for the "dummy" header and the record markers - the record marker bytes are
3133// in the files - they are just written as zeros and are meaningless
3134//file is:
3135//      516 bytes header
3136// 128x128=16384 (x4) bytes of data
3137// + 2 byte record markers interspersed just for fun
3138// = 66116 bytes
3139//prompts for name of the output file.
3140//
3141Function WriteVAXWorkFile(type)
3142        String type
3143       
3144        Wave data=$("root:Packages:NIST:"+type+":data")
3145       
3146        Variable refnum,ii=0,hdrBytes=516,a,b,offset
3147        String fullpath=""
3148       
3149        Duplicate/O data,tempData
3150        Redimension/S/N=(128*128) tempData
3151        tempData *= 4
3152       
3153        PathInfo/S catPathName
3154        fullPath = DoSaveFileDialog("Save data as")       //won't actually open the file
3155        If(cmpstr(fullPath,"")==0)
3156                //user cancel, don't write out a file
3157          Close/A
3158          Abort "no data file was written"
3159        Endif
3160       
3161        Make/B/O/N=(hdrBytes) hdrWave
3162        hdrWave=0
3163        FakeDIVHeader(hdrWave)
3164       
3165        Make/Y=2/O/N=(510) bw510                //Y=2 specifies 32 bit (=4 byte) floating point
3166        Make/Y=2/O/N=(511) bw511
3167        Make/Y=2/O/N=(48) bw48
3168
3169        Make/O/B/N=2 recWave            //two bytes
3170
3171        //actually open the file
3172        Open/C="????"/T="TEXT" refNum as fullpath
3173        FSetPos refNum, 0
3174        //write header bytes (to be skipped when reading the file later)
3175       
3176        FBinWrite /F=1 refnum,hdrWave
3177       
3178        ii=0
3179        a=0
3180        do
3181                //write 511 4-byte values (little-endian order), 4* true value
3182                bw511[] = tempData[p+a]
3183                FBinWrite /B=3/F=4 refnum,bw511
3184                a+=511
3185                //write a 2-byte record marker
3186                FBinWrite refnum,recWave
3187               
3188                //write 510 4-byte values (little-endian) 4* true value
3189                bw510[] = tempData[p+a]
3190                FBinWrite /B=3/F=4 refnum,bw510
3191                a+=510
3192               
3193                //write a 2-byte record marker
3194                FBinWrite refnum,recWave
3195               
3196                ii+=1   
3197        while(ii<16)
3198        //write out last 48  4-byte values (little-endian) 4* true value
3199        bw48[] = tempData[p+a]
3200        FBinWrite /B=3/F=4 refnum,bw48
3201        //close the file
3202        Close refnum
3203       
3204        //go back through and make it look like a VAX datafile
3205        Make/W/U/O/N=(511*2) int511             // /W=16 bit signed integers /U=unsigned
3206        Make/W/U/O/N=(510*2) int510
3207        Make/W/U/O/N=(48*2) int48
3208       
3209        //skip the header for now
3210        Open/A/T="????TEXT" refnum as fullPath
3211        FSetPos refnum,0
3212       
3213        offset=hdrBytes
3214        ii=0
3215        do
3216                //511*2 integers
3217                FSetPos refnum,offset
3218                FBinRead/B=2/F=2 refnum,int511
3219                Swap16BWave(int511)
3220                FSetPos refnum,offset
3221                FBinWrite/B=2/F=2 refnum,int511
3222               
3223                //skip 511 4-byte FP = (511*2)*2 2byte int  + 2 bytes record marker
3224                offset += 511*2*2 + 2
3225               
3226                //510*2 integers
3227                FSetPos refnum,offset
3228                FBinRead/B=2/F=2 refnum,int510
3229                Swap16BWave(int510)
3230                FSetPos refnum,offset
3231                FBinWrite/B=2/F=2 refnum,int510
3232               
3233                //
3234                offset += 510*2*2 + 2
3235               
3236                ii+=1
3237        while(ii<16)
3238        //48*2 integers
3239        FSetPos refnum,offset
3240        FBinRead/B=2/F=2 refnum,int48
3241        Swap16BWave(int48)
3242        FSetPos refnum,offset
3243        FBinWrite/B=2/F=2 refnum,int48
3244
3245        //move to EOF and close
3246        FStatus refnum
3247        FSetPos refnum,V_logEOF
3248       
3249        Close refnum
3250       
3251        Killwaves/Z hdrWave,bw48,bw511,bw510,recWave,temp16,int511,int510,int48
3252End
3253
3254// given a 16 bit integer wave, read in as 2-byte pairs of 32-bit FP data
3255// swap the order of the 2-byte pairs
3256//
3257Function Swap16BWave(w)
3258        Wave w
3259
3260        Duplicate/O w,temp16
3261        //Variable num=numpnts(w),ii=0
3262
3263        //elegant way to swap even/odd values, using wave assignments
3264        w[0,*;2] = temp16[p+1]
3265        w[1,*;2] = temp16[p-1]
3266
3267//crude way, using a loop       
3268//      for(ii=0;ii<num;ii+=2)
3269//              w[ii] = temp16[ii+1]
3270//              w[ii+1] = temp16[ii]
3271//      endfor
3272       
3273        return(0)       
3274End
3275
3276// writes a fake label into the header of the DIV file
3277//
3278Function FakeDIVHeader(hdrWave)
3279        WAVE hdrWave
3280       
3281        //put some fake text into the sample label position (60 characters=60 bytes)
3282        String day=date(),tim=time(),lbl=""
3283        Variable start=98,num,ii
3284       
3285        lbl = "Sensitivity (DIV) created "+day +" "+tim
3286        num=strlen(lbl)
3287        for(ii=0;ii<num;ii+=1)
3288                hdrWave[start+ii] = char2num(lbl[ii])
3289        endfor
3290
3291        return(0)
3292End
3293
3294////////end of ProDiv() specifics
3295
3296
3297// JUL 2013
3298// Yet another fix for an ICE issue. Here the issue is when the run number gets "magically"
3299// reset during an experiment. Then there are duplicate run numbers. When procedures key on the run number,
3300// the *first* file in the OS file listing is the one that's found. Simply renaming the file with a
3301// different number is not sufficient, as the file name embedded in the header must be used (typically from
3302// marquee operations) where there is a disconnect between the file load and the function - leading to
3303// cases where the current data is "unknown", except for textRead.
3304//
3305// Hence more patching procedures to re-write files with new file names in the header and the OS.
3306//
3307Proc RenumberRunNumber(add)
3308        Variable add
3309
3310        fRenumberRunNumber(add)
3311
3312End
3313
3314Proc CheckFileNames(firstFile,lastFile)
3315        Variable firstFile=1,lastFile=100
3316       
3317        fCheckFileNames(firstFile,lastFile)
3318End
3319
3320
3321// will read the 21 character file name and put any spaces at the front of the string
3322// like the VAX does. Should have absolutely no effect if there are spaces at the
3323// beginning of the string, as the VAX does.
3324Function fRenumberRunNumber(add)
3325        Variable add
3326       
3327        Variable ii,numItems
3328        String item,runStr,list
3329        String curFile,newRunStr,newFileStr
3330        String pathStr
3331        PathInfo catPathName
3332        pathStr = S_path
3333       
3334// get a list of all of the files in the folder
3335        list = IndexedFile(catPathName,-1,"????")       //get all files in folder
3336        numItems = ItemsInList(list,";")                //get the new number of items in the list
3337
3338// for each file
3339        for(ii=0;ii<numItems;ii+=1)
3340                curFile = StringFromList(ii, list  ,";" )
3341                runStr = GetRunNumStrFromFile(curFile)
3342               
3343                if(cmpstr(runStr,"ABC") != 0)           // weed out error if run number can't be found
3344                        newRunStr = num2str( str2num(runStr) + add )
3345                        newFileStr = ReplaceString(runStr, curFile, newRunStr )
3346                // change the file name on disk to have a new number (+add)
3347                        Printf "Old = %s\t\tNew = %s\r",curFile,newFileStr
3348                       
3349                // copy the file, saving with the new name
3350                        CopyFile/I=0/O/P=catPathName curFile as newFileStr
3351                       
3352                // change the run number in the file header to have the new number (writing just the necessary characters)
3353                        WriteTextToHeader(pathStr+newFileStr,newRunStr,7)               //start at byte 7
3354                endif
3355                                       
3356        endfor
3357       
3358        return(0)
3359End
3360
3361// simple utility to read the file name stored in the file header (and the suffix)
3362Function fCheckFileNames(lo,hi)
3363        Variable lo,hi
3364       
3365        String file,fileName,suffix,fileInHdr,fileOnDisk
3366        Variable ii
3367       
3368        for(ii=lo;ii<=hi;ii+=1)
3369                file = FindFileFromRunNumber(ii)
3370                if(strlen(file) != 0)
3371                        fileOnDisk = ParseFilePath(0, file, ":", 1, 0)
3372                        fileInHdr = getFileName(file)
3373//                      suffix = getSuffix(file)
3374                        printf "File %d:  File on disk = %s\t\tFile in Hdr = %s\r",ii,fileOnDisk,fileInHdr
3375                else
3376                        printf "run number %d not found\r",ii
3377                endif
3378        endfor
3379       
3380        return(0)
3381End
3382
Note: See TracBrowser for help on using the repository browser.