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

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

Lots of changes:
-2D resolution smearing
-2D error propagation

1) 2D resolution smearing has been corrected to use sigma (perp) correctly
rather than phi. This shows up in the quadrature loop in all of the 2D models
and in the Smear_2D "generic" function.

2) 1D resolutionn smearing is now corrected to account for the integration
range of +/- 3 sigma (99.73% of distribution). Now the result is divided by
0.9973 to rescale it to the correct value.

3) Smeared models are now AAO to improve speed and to allow easier use with
functions that are inherently AAO. No changes are needed, since the call is
behind the scenes, replacing Smear_Model_N() with Smear_Model_N_AAO().

4) in PlotUtils_2D added functions to re-bin the QxQy? data into a 1D format
BinQxQy_to_1D(). This also re-bins the errors in two ways, adding the per-pixel
errors in quadrature, or the deviation from the mean of the intensity. Manually
editing the intensity declaration allows 2D->1D binning of smeared models.

5) Per-pixel propagation of errors has been added through the entire data
reduction sequence. Data errors are generated on loading using Poisson
statistics (specifically tailored for accuracy at low counts) and then is
propagated through each manipulation of the data using standard error
propagation. The error matrix is linear_data_error. As a by-product, all of
the math operations on data are explicitly done on linear_data, to avoid
any potential mistakes of log/linear scaling. Results of this propagation
largely match J. Barker's /ERROR routines from the VAX, with some differences
at low data count values (as expected) and at higher count values near the
beam stop (somewhat unexpected). This per-pixel error is ouput in the QxQy_ASCII
data files. NO CHANGE has been made to the 1D data, which uses the deviation from
the mean as the error - since this is correct.

6) Added tables for the uncertainty in attenuator transmission (from JGB)

7) added two more REAL values to the VAX header to store information
necessary for error propagation. These are couting error that are part of
the transmission error and of the absolute scaling error. These add Read/Write?
functions in NCNR_DataReadWrite

The transmission error (one standard deviation) is written at byte 396 (4 bytes)

RealsRead?[41]

The Box Sum error (one standard deviation) is written at byte 400 (4 bytes)

RealsRead?[42]

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