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

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

changes to the calls to GBLoadWave to now use a path and only the file name. Previously I use the full path:name to construct the execute statement.

this is being done to try to act as a workaround for network neighborhood paths in windows 10 (where drives can't be mapped)

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