source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/SANS/NCNR_DataReadWrite_HDF5.ipf @ 946

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

Adding procedures that will allow read/write of raw data in HDF5 format. No Nexus file definition has been settled upon yet, so I made up my own for testing, simply converting what was present in the VAX file header. Simple read/write operations are functional, but no full scale testing.

Transmission calculation is partially broken as there are no file suffixes anymore.

Otherwise, a good starting point for the HDF5/Nexus of the future.

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