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

Last change on this file since 779 was 776, checked in by srkline, 12 years ago

fixed some sloppy logic in converting log/lin data. Now the raw data readers create data (for display) and linear_data (to keep) upon loading.

Updated the Histogram Pair with Cedric's suggestions. width is adjustable, and the cursor is more visible.

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