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

Last change on this file since 940 was 940, checked in by srkline, 9 years ago

Updated the reduction Read/Write? and corresponding factility stubs to accomodate detector dead time written to the VAX header. It is currently not written to the header, but may be with NICE (hopefully).

With the move of NG3 SANS to CGB(upper), the NG3 designation in the account name [NGxSANSxx] has been replaced with CGB. Folders on charlotte and radio button on SASCALC are labeled "NGB30" to be more obvious which instrument it is.

FFT routines have minor typos cleaned up.

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