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

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

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

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

File size: 53.8 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma version=5.0
3#pragma IgorVersion = 6.1 //required to read and write files created with HDF 1.8 library
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
44        ReadHeaderAndData(filename)     //this is the full Path+file
45       
46        Return(0)
47End
48
49
50//function that does the guts of reading the binary data file
51//fname is the full path:name;vers required to open the file
52//
53// The final root:Packages:NIST:RAW:data wave is the real
54//neutron counts and can be directly operated on
55//
56// header information is put into three waves: integersRead, realsRead, and textRead
57// logicals in the header are currently skipped, since they are no use in the
58// data reduction process.
59//
60// The output is the three R/T/I waves that are filled at least with minimal values
61// and the detector data loaded into an array named "data"
62//
63// see documentation for the expected information in each element of the R/T/I waves
64// and the minimum set of information. These waves can be increased in length so that
65// more information can be accessed as needed (propagating changes...)
66//
67// called by multiple .ipfs (when the file name is known)
68//
69//
70// THIS FUNCTION DOES NOT NEED TO BE MODIFIED. ONLY THE DATA ACCESSORS NEED TO BE CONSTRUCTED
71//
72Function ReadHeaderAndData(fname)
73        String fname
74        //this function is for reading in RAW data only, so it will always put data in RAW folder
75        String curPath = "root:Packages:NIST:RAW"
76        SetDataFolder curPath           //use the full path, so it will always work
77        variable/g root:Packages:NIST:RAW:gIsLogScale = 0               //initial state is linear, keep this in RAW folder
78       
79        Variable refNum,integer,realval
80        String sansfname,textstr
81       
82        Make/D/O/N=23 $"root:Packages:NIST:RAW:IntegersRead"
83        Make/D/O/N=52 $"root:Packages:NIST:RAW:RealsRead"
84        Make/O/T/N=11 $"root:Packages:NIST:RAW:TextRead"
85        Make/O/N=7 $"root:Packages:NIST:RAW:LogicalsRead"
86
87        Wave intw=$"root:Packages:NIST:RAW:IntegersRead"
88        Wave realw=$"root:Packages:NIST:RAW:RealsRead"
89        Wave/T textw=$"root:Packages:NIST:RAW:TextRead"
90        Wave logw=$"root:Packages:NIST:RAW:LogicalsRead"
91       
92        // FILL IN 3 ARRAYS WITH HEADER INFORMATION FOR LATER USE
93        // THESE ARE JUST THE MINIMALLY NECESSARY VALUES
94       
95        // filename as stored in the file header
96        textw[0]= ParseFilePath(0, fname, ":", 1, 0)   
97       
98        // date and time of collection
99        textw[1]= getFileCreationDate(fname)
100       
101        // run type identifier (this is a reader for RAW data)
102        textw[2]= "RAW"
103       
104        // user account identifier (currently used only for NCNR-specific operations)
105        textw[3]= ""
106
107        // sample label
108        textw[6]= getSampleLabel(fname)
109       
110        // identifier of detector type, useful for setting detector constants
111        //(currently used only for NCNR-specific operations)
112        textw[9]= ""
113
114        //total counting time in seconds
115        intw[2] = getCountTime(fname)
116       
117//      realw[1] = 0
118//      realw[6] = 0
119//      realw[7] = 0
120//      realw[8] = 0
121//      realw[9] = 0
122//      realw[19] = 0
123//      realw[22] = 0
124
125        // total monitor count
126        realw[0] = getMonitorCount(fname)
127
128       
129        // attenuator number (NCNR-specific, your stub returns 0)
130        // may also be used to hold attenuator transmission (< 1)
131        realw[3] = getAttenNumber(fname)
132       
133        // sample transmission
134        realw[4] = getSampleTrans(fname)
135       
136        //sample thickness (cm)
137        realw[5] = getSampleThickness(fname)
138       
139        // following 6 values are for non-linear spatial corrections to a detector (RC timing)
140        // these values are set for a detctor that has a linear correspondence between
141        // pixel number and real-space distance
142        // 10 and 13 are the X and Y pixel dimensions, respectively (in mm!)
143        //(11,12 and 13,14 are set to values for a linear response, as from a new Ordela detector)
144        realw[10] = getDetectorPixelXSize(fname)
145        realw[11] = 10000
146        realw[12] = 0
147        realw[13] = getDetectorPixelYSize(fname)
148        realw[14] = 10000
149        realw[15] = 0
150       
151        // beam center X,Y on the detector (in units of pixel coordinates (1,N))
152        realw[16] = getBeamXPos(fname)
153        realw[17] = getBeamYPos(fname)
154       
155        // sample to detector distance (meters)
156        realw[18] = getSDD(fname)
157
158        // detector physical width (right now assumes square...) (in cm)
159        //realw[20] = 65
160        realw[20] = getPhysicalWidth(fname)
161       
162        // beam stop diameter (assumes circular) (in mm)
163        realw[21] = getBSDiameter(fname)
164       
165        // source aperture diameter (mm)
166        realw[23] = getSourceApertureDiam(fname)
167       
168        // sample aperture diameter (mm)
169        realw[24] = getSampleApertureDiam(fname)
170       
171        // source aperture to sample aperture distance
172        realw[25] = getSourceToSampleDist(fname)
173       
174        // wavelength (A)
175        realw[26] = getWavelength(fname)
176       
177        // wavelength spread (FWHM)
178        realw[27] = getWavelengthSpread(fname)
179       
180        // beam stop X-position (motor reading, approximate cm from zero position)
181        // currently NCNR-specific use to identify transmission measurements
182        // you return 0
183        realw[37] = 0
184
185// the actual data array, dimensions are set as globals in
186// InitFacilityGlobals()
187        NVAR XPix = root:myGlobals:gNPixelsX
188        NVAR YPix = root:myGlobals:gNPixelsX
189       
190        Make/D/O/N=(XPix,YPix) $"root:Packages:NIST:RAW:data"
191        WAVE data=$"root:Packages:NIST:RAW:data"
192
193        // fill the data array with the detector values
194        getDetectorData(fname,data)
195       
196        // total detector count
197        //nha 21/5/10 moved here because it requires the detector data to already be written
198        //Result of issue with 0 counts being written for a while in metadata.
199        realw[2] = getDetCount(fname)
200       
201        //keep a string with the filename in the RAW folder
202        String/G root:Packages:NIST:RAW:fileList = textw[0]
203       
204        Duplicate/O data $"root:Packages:NIST:RAW:linear_data"                  //data read in is on linear scale, copy it now
205
206        Return 0
207
208End
209
210//****************
211//main entry procedure for reading a "WORK.DIV" file
212//displays a quick image of the  file, to check that it's correct
213//data is deposited in root:Packages:NIST:DIV data folder
214//
215// local, just for testing
216//
217Proc ReadWork_DIV()
218       
219        String fname = PromptForPath("Select detector sensitivity file")
220        ReadHeaderAndWork("DIV",fname)          //puts what is read in work.div
221       
222        String waveStr = "root:Packages:NIST:DIV:data"
223        NewImage/F/K=1/S=2 $waveStr
224        ModifyImage '' ctab= {*,*,YellowHot,0}
225       
226        String/G root:Packages:NIST:DIV:fileList = "WORK.DIV"
227       
228        SetDataFolder root:             //(redundant)
229End
230
231
232
233// Detector sensitivity files have the same header structure as RAW SANS data
234// as NCNR, just with a different data array (real, rather than integer data)
235//
236// So for your facility, make this reader specific to the format of whatever
237// file you use for a pixel-by-pixel division of the raw detector data
238// to correct for non-uniform sensitivities of the detector. This is typically a
239// measurement of water, plexiglas, or another uniform scattering sample.
240//
241// The data must be normalized to a mean value of 1
242//
243// called from ProtocolAsPanel.ipf
244//
245// type is "DIV" on input
246Function ReadHeaderAndWork(type,fname)
247        String type,fname
248       
249        //type is the desired folder to read the workfile to
250        //this data will NOT be automatically displayed
251        // gDataDisplayType is unchanged
252
253        String cur_folder = type
254        String curPath = "root:Packages:NIST:"+cur_folder
255        SetDataFolder curPath           //use the full path, so it will always work
256       
257        Variable refNum,integer,realval
258        String sansfname,textstr
259        Variable/G $(curPath + ":gIsLogScale") = 0              //initial state is linear, keep this in DIV folder
260       
261        Make/O/D/N=23 $(curPath + ":IntegersRead")
262        Make/O/D/N=52 $(curPath + ":RealsRead")
263        Make/O/T/N=11 $(curPath + ":TextRead")
264       
265        WAVE intw=$(curPath + ":IntegersRead")
266        WAVE realw=$(curPath + ":RealsRead")
267        WAVE/T textw=$(curPath + ":TextRead")
268       
269        // the actual data array, dimensions are set as globals in
270        // InitFacilityGlobals()
271        NVAR XPix = root:myGlobals:gNPixelsX
272        NVAR YPix = root:myGlobals:gNPixelsX
273
274        Make/O/D/N=(XPix,YPix) $(curPath + ":data")
275        WAVE data = $(curPath + ":data")
276       
277        // (1)
278        // fill in your reader for the header here so that intw, realw, and textW are filled in
279        // ? possibly a duplication of the raw data reader
280               
281        //(2)
282        // then fill in a reader for the data array that will DIVIDE your data
283        // to get the corrected values.
284        String dfName=""
285        variable err
286        err = hdfRead(fname, dfName)
287        Wave tempData = $dfName+":data:div"
288        data = tempData
289       
290        //funky edge correction bodgy ???
291        //copy second column to first column
292        data[][0] = data[p][1]
293        //copy second last column to last column
294        data[][191] = data[p][190]
295        //copy second row to first row
296        data[0][] = data[1][q]
297        //copy second last row to last row
298        data[191][] = data[190][q]
299        //keep a string with the filename in the DIV folder
300        String/G $(curPath + ":fileList") = textw[0]
301       
302        Duplicate/O data linear_data                    //data read in is on linear scale, copy it now
303
304        //return the data folder to root
305        SetDataFolder root:
306       
307        Return(0)
308End
309
310Function WriteHeaderAndWork(type)
311        String type
312       
313        // your writer here
314        NVAR XPix = root:myGlobals:gNPixelsX
315        NVAR YPix = root:myGlobals:gNPixelsX   
316       
317        Wave wData=$("root:Packages:NIST:"+type+":data")
318       
319//      Variable refnum,ii=0,hdrBytes=516,a,b,offset
320        String fname=""
321//      Duplicate/O wData,tempData
322       
323        //changed for Quokka
324//      Redimension/S/N=(XPix*YPix) tempData
325//      tempData *= 4
326       
327        PathInfo/S catPathName
328        fname = DoSaveFileDialog("Save data as")          //won't actually open the file
329        If(cmpstr(fname,"")==0)
330                //user cancel, don't write out a file
331          Close/A
332          Abort "no data file was written"
333        Endif
334       
335        variable fileID
336        HDF5CreateFile /O fileID as fname
337       
338        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
339        //Make /N=(1,1) wTransmission
340        String groupName = "/reduce"
341        String varName = "div"
342        // your code returning value
343        variable err
344        err = hdfWrite(fname, groupName, varName, wData)
345
346        // KillWaves wData, tempData
347        return(0)
348End
349
350
351
352/////   ASC FORMAT READER  //////
353/////   FOR WORKFILE MATH PANEL //////
354//
355//function to read in the ASC output of SANS reduction
356// currently the file has 20 header lines, followed by a single column
357// of 16384 values, Data is written by row, starting with Y=1 and X=(1->128)
358//
359//returns 0 if read was ok
360//returns 1 if there was an error
361//
362// called by WorkFileUtils.ipf
363//
364//
365// If the ASC data was generated by the NCNR data writer, then
366// NOTHING NEEDS TO BE CHANGED HERE
367//
368Function ReadASCData(fname,destPath)
369        String fname, destPath
370        //this function is for reading in ASCII data so put data in user-specified folder
371        SetDataFolder "root:Packages:NIST:"+destPath
372
373        NVAR pixelsX = root:myGlobals:gNPixelsX
374        NVAR pixelsY = root:myGlobals:gNPixelsY
375        Variable refNum=0,ii,p1,p2,tot,num=pixelsX,numHdrLines=20
376        String str=""
377        //data is initially linear scale
378        Variable/G :gIsLogScale=0
379        Make/O/T/N=(numHdrLines) hdrLines
380        Make/O/D/N=(pixelsX*pixelsY) data                       //,linear_data
381       
382        //full filename and path is now passed in...
383        //actually open the file
384//      SetDataFolder destPath
385        Open/R/Z refNum as fname                // /Z flag means I must handle open errors
386        if(refnum==0)           //FNF error, get out
387                DoAlert 0,"Could not find file: "+fname
388                Close/A
389                SetDataFolder root:
390                return(1)
391        endif
392        if(V_flag!=0)
393                DoAlert 0,"File open error: V_flag="+num2Str(V_Flag)
394                Close/A
395                SetDataFolder root:
396                return(1)
397        Endif
398        //
399        for(ii=0;ii<numHdrLines;ii+=1)          //read (or skip) 18 header lines
400                FReadLine refnum,str
401                hdrLines[ii]=str
402        endfor
403        //     
404        Close refnum
405       
406//      SetDataFolder destPath
407        LoadWave/Q/G/D/N=temp fName
408        Wave/Z temp0=temp0
409        data=temp0
410        Redimension/N=(pixelsX,pixelsY) data            //,linear_data
411       
412        //linear_data = data
413       
414        KillWaves/Z temp0
415       
416        //return the data folder to root
417        SetDataFolder root:
418       
419        Return(0)
420End
421
422// fills the "default" fake header so that the SANS Reduction machinery does not have to be altered
423// pay attention to what is/not to be trusted due to "fake" information.
424// uses what it can from the header lines from the ASC file (hdrLines wave)
425//
426// destFolder is of the form "myGlobals:WorkMath:AAA"
427//
428//
429// called by WorkFileUtils.ipf
430//
431// If the ASC data was generated by the NCNR data writer, then
432// NOTHING NEEDS TO BE CHANGED HERE
433//
434Function FillFakeHeader_ASC(destFolder)
435        String destFolder
436        Make/O/D/N=23 $("root:Packages:NIST:"+destFolder+":IntegersRead")
437        Make/O/D/N=52 $("root:Packages:NIST:"+destFolder+":RealsRead")
438        Make/O/T/N=11 $("root:Packages:NIST:"+destFolder+":TextRead")
439       
440        Wave intw=$("root:Packages:NIST:"+destFolder+":IntegersRead")
441        Wave realw=$("root:Packages:NIST:"+destFolder+":RealsRead")
442        Wave/T textw=$("root:Packages:NIST:"+destFolder+":TextRead")
443       
444        //Put in appropriate "fake" values
445        //parse values as needed from headerLines
446        Wave/T hdr=$("root:Packages:NIST:"+destFolder+":hdrLines")
447        Variable monCt,lam,offset,sdd,trans,thick
448        Variable xCtr,yCtr,a1,a2,a1a2Dist,dlam,bsDiam
449        String detTyp=""
450        String tempStr="",formatStr="",junkStr=""
451        formatStr = "%g %g %g %g %g %g"
452        tempStr=hdr[3]
453        sscanf tempStr, formatStr, monCt,lam,offset,sdd,trans,thick
454//      Print monCt,lam,offset,sdd,trans,thick,avStr,step
455        formatStr = "%g %g %g %g %g %g %g %s"
456        tempStr=hdr[5]
457        sscanf tempStr,formatStr,xCtr,yCtr,a1,a2,a1a2Dist,dlam,bsDiam,detTyp
458//      Print xCtr,yCtr,a1,a2,a1a2Dist,dlam,bsDiam,detTyp
459       
460        realw[16]=xCtr          //xCtr(pixels)
461        realw[17]=yCtr  //yCtr (pixels)
462        realw[18]=sdd           //SDD (m)
463        realw[26]=lam           //wavelength (A)
464        //
465        // necessary values
466        realw[10]=5                     //detector calibration constants, needed for averaging
467        realw[11]=10000
468        realw[12]=0
469        realw[13]=5
470        realw[14]=10000
471        realw[15]=0
472        //
473        // used in the resolution calculation, ONLY here to keep the routine from crashing
474        realw[20]=65            //det size
475        realw[27]=dlam  //delta lambda
476        realw[21]=bsDiam        //BS size
477        realw[23]=a1            //A1
478        realw[24]=a2    //A2
479        realw[25]=a1a2Dist      //A1A2 distance
480        realw[4]=trans          //trans
481        realw[3]=0              //atten
482        realw[5]=thick          //thick
483        //
484        //
485        realw[0]=monCt          //def mon cts
486
487        // fake values to get valid deadtime and detector constants
488        //
489        textw[9]=detTyp+"  "            //6 characters 4+2 spaces
490        textw[3]="[NGxSANS00]"  //11 chars, NGx will return default values for atten trans, deadtime...
491       
492        //set the string values
493        formatStr="FILE: %s CREATED: %s"
494        sscanf hdr[0],formatStr,tempStr,junkStr
495//      Print tempStr
496//      Print junkStr
497        String/G $("root:Packages:NIST:"+destFolder+":fileList") = tempStr
498        textw[0] = tempStr              //filename
499        textw[1] = junkStr              //run date-time
500       
501        //file label = hdr[1]
502        tempStr = hdr[1]
503        tempStr = tempStr[0,strlen(tempStr)-2]          //clean off the last LF
504//      Print tempStr
505        textW[6] = tempStr      //sample label
506       
507        return(0)
508End
509
510
511///////// ACCESSORS FOR WRITING DATA TO HEADER  /////////
512/////
513
514// Write* routines all must:
515// (1) open file "fname". fname is a full file path and name to the file on disk
516// (2) write the specified value to the header at the correct location in the file
517// (3) close the file
518
519
520
521//whole transmission is NCNR-specific right now
522// leave this stub empty
523Function WriteWholeTransToHeader(fname,wholeTrans)
524        String fname
525        Variable wholeTrans
526       
527        String groupName = "/reduce"
528        variable err
529       
530        Wave wCounts
531        Make /N=(1,1) wWholeTrans
532               
533        wWholeTrans[0] = wholeTrans
534       
535        String varName = "wholeTransmission"   
536        err = hdfWrite(fname, groupName, varName,wWholeTrans)
537
538        KillWaves wWholeTrans
539       
540        //err not handled here
541        return(0)       
542End
543
544//box sum counts is a real value
545// used for transmission calculation module
546Function WriteBoxCountsToHeader(fname,counts)
547        String fname
548        Variable counts
549       
550        // do nothing if not using NCNR Transmission module
551       
552        String groupName = "/reduce"
553        variable err
554       
555        Wave wCounts
556        Make /N=(1,1) wCounts
557               
558        wCounts[0] = counts
559       
560        String varName = "boxCounts"   
561        err = hdfWrite(fname, groupName, varName,wCounts)
562
563        KillWaves wCounts
564       
565        //err not handled here
566        return(0)       
567End
568
569//beam stop X-position
570// used for transmission module to manually tag transmission files
571Function WriteBSXPosToHeader(fname,xpos)
572        String fname
573        Variable xpos
574       
575        // do nothing if not using NCNR Transmission module
576       
577        return(0)
578End
579
580
581
582
583
584//attenuator number (not its transmission)
585// if your beam attenuation is indexed in some way, use that number here
586// if not, write a 1 to the file here as a default
587//
588Function WriteAttenNumberToHeader(fname,attenNumber)
589        String fname
590        Variable attenNumber
591       
592        // your writer here
593        Wave wAttenNumber
594        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
595        Make /N=(1,1) wAttenNumber
596        String groupName = "/instrument/collimator"
597        String varName = "att"
598        //convert number to a rotation angle
599        attenNumber = attenNumber * 30
600        wAttenNumber[0] = attenNumber //
601        // your code returning value
602        variable err
603        err = hdfWrite(fname, groupName, varName, wAttenNumber)
604        KillWaves wAttenNumber
605        //err not handled here
606               
607        return(0)
608
609End
610
611
612// total monitor count during data collection
613Function WriteMonitorCountToHeader(fname,num)
614        String fname
615        Variable num
616       
617        // your code here
618       
619        return(0)
620End
621
622//total detector count
623Function WriteDetectorCountToHeader(fname,num)
624        String fname
625        Variable num
626       
627        // your code here
628       
629        return(0)
630End
631
632//transmission detector count
633// (currently unused in data reduction)
634Function WriteTransDetCountToHeader(fname,num)
635        String fname
636        Variable num
637       
638        // do nothing for now
639       
640        return(0)
641End
642
643
644
645//temperature of the sample (C)
646Function WriteTemperatureToHeader(fname,num)
647        String fname
648        Variable num
649       
650        //  your code here
651       
652        return(0)
653End
654
655//magnetic field (Oe)
656Function WriteMagnFieldToHeader(fname,num)
657        String fname
658        Variable num
659       
660        // your code here
661       
662        return(0)
663End
664
665//lateral detector offset (centimeters)
666Function WriteDetectorOffsetToHeader(fname,DetectorOffset)
667        String fname
668        Variable DetectorOffset
669       
670        // your writer here
671        Wave wDetectorOffset
672        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
673        Make /N=(1,1) wDetectorOffset
674        String groupName = "/instrument/detector"
675        String varName = "detector_x"
676        //convert from cm (NIST standard) to mm (NeXus standard)
677        DetectorOffset = DetectorOffset * 10
678        wDetectorOffset[0] = DetectorOffset //
679        // your code returning value
680        variable err
681        err = hdfWrite(fname, groupName, varName, wDetectorOffset)
682        KillWaves wDetectorOffset
683        //err not handled here
684       
685        return(0)
686End
687
688
689
690
691// physical dimension of detector x-pixel (mm)
692Function WriteDetPixelXToHeader(fname,num)
693        String fname
694        Variable num
695       
696        //your code here
697       
698        return(0)
699end
700
701// physical dimension of detector y-pixel (mm)
702Function WriteDetPixelYToHeader(fname,num)
703        String fname
704        Variable num
705       
706        //your code here
707       
708        return(0)
709end
710
711// sample label string
712Function WriteSamLabelToHeader(fname,str)
713        String fname,str
714       
715        // your code here
716
717        return(0)
718End
719
720// total counting time (seconds)
721Function WriteCountTimeToHeader(fname,num)
722        String fname
723        Variable num
724       
725        // your code here
726       
727        return(0)
728End
729
730
731
732//////// ACCESSORS FOR READING DATA FROM THE HEADER  //////////////
733//
734// read specific bits of information from the header
735// each of these operations MUST take care of open/close on their own
736//
737// fname is the full path and filname to the file on disk
738// return values are either strings or real values as appropriate
739//
740//////
741
742
743// function that reads in the 2D detector data and fills the array
744// data[nx][ny] with the data values
745// fname is the full name and path to the data file for opening and closing
746//
747//
748Function getDetectorData(fname,data)
749        String fname
750        Wave data
751        NVAR XPix = root:myGlobals:gNPixelsX
752       
753        // your reader here
754        variable err
755        string dfName = ""
756        err = hdfRead(fname, dfName)
757        if(err)
758                return 0
759        endif
760
761        Wave hmm_xy = $(dfName+":data:hmm_xy")
762       
763        //redimension /I /N = (dimsize(hmm_xy, 2), dimsize(hmm_xy, 1)), data
764        //nha. Count arrays need to be floating point, since the data will be divided, normalised etc.
765        redimension /N = (dimsize(hmm_xy, 2), dimsize(hmm_xy, 1)), data
766        data[][] = hmm_xy[0][q][p]
767       
768        //nha workaround. for wrongly dimensioned Quokka data 191x192
769        variable x_dim = dimsize(data,0)
770        if (x_dim!=XPix)
771                //redimension to add an extra row(s) to the data
772                redimension /I /N = (XPix,-1) data
773                //copy row 190 to row 191
774                data[191][] = data[190][q]
775        endif   
776        // end workaround
777       
778        //funky edge correction bodgy ???
779        //copy second column to first column
780        data[][0] = data[p][1]
781        //copy second last column to last column
782        data[][191] = data[p][190]
783        //copy second row to first row
784        data[0][] = data[1][q]
785        //copy second last row to last row
786        data[191][] = data[190][q]
787                       
788        KillWaves hmm_xy
789       
790       
791        return(0)
792End
793
794// file suffix (NCNR data file name specific)
795// return filename as suffix
796Function/S getSuffix(fname)
797        String fname
798       
799        return(ParseFilePath(0, fname, ":", 1, 0))
800End
801
802// associated file suffix (for transmission)
803// NCNR Transmission calculation specific
804// return null string
805Function/S getAssociatedFileSuffix(fname)
806        String fname
807       
808        return(getFileAssoc(fname))
809End
810
811// sample label
812Function/S getSampleLabel(fname)
813        String fname
814        String str
815       
816        // your code, returning str
817        variable err
818        string dfName = ""
819        err = hdfRead(fname, dfName)
820        //err not handled here
821       
822        Wave/T wSampleName = $dfname+":sample:name"
823        str = wSampleName[0]
824        KillWaves wSampleName
825       
826        return(str)
827End
828
829// file creation date
830Function/S getFileCreationDate(fname)
831        String fname
832        String str
833       
834        // your code, returning str
835        variable err
836        string dfName = ""
837        err = hdfRead(fname, dfName)
838        //err not handled here
839       
840        Wave/T wStartTime = $dfName+":start_time"
841        str = wStartTime[0]
842        KillWaves wStartTime
843       
844        return(str)
845End
846
847
848//monitor count
849Function getMonitorCount(fname)
850//not patched
851        String fname
852        Variable value
853       
854        // your code returning value
855        variable err
856        string dfName = ""
857        err = hdfRead(fname, dfName)
858        //err not handled here
859       
860        Wave wCounts = $dfName+":monitor:bm1_counts"
861        value = wCounts[0]
862        KillWaves wCounts
863       
864        return(value)
865end
866
867//saved monitor count
868// NCNR specific for pre-processed data, never used
869// return 0
870Function getSavMon(fname)
871        String fname
872       
873        Variable value
874       
875        // your code returning value
876        //??? to do. Is this required if 'never used'? nha
877       
878        return(0)
879end
880
881//total detector count
882Function getDetCount(fname)
883//not patched, but could be
884        String fname
885        Variable value
886       
887        // your code returning value
888        variable err
889        string dfName = ""
890        err = hdfRead(fname, dfName)
891        //err not handled here
892
893        //      Wave wCounts = $(dfName+":data:total_counts")
894        // changed 22/12/09 nha
895                if(WaveExists($(dfName+":data:total_counts")))
896                        Wave wCounts = $(dfName+":data:total_counts")
897                elseif(WaveExists($(dfName+":instrument:detector:total_counts")))
898                Wave wCounts = $(dfName+":instrument:detector:total_counts")
899               else
900                print "Can't find detector total_counts in " + fname
901               endif
902       
903        value = wCounts[0]
904       
905        //nha 21/5/10 temporary glitch wrote detector count to file as 0       
906                if (value<1)
907                        NVAR XPix = root:myGlobals:gNPixelsX
908                        NVAR YPix = root:myGlobals:gNPixelsX
909                        Make/D/O/N=(XPix,YPix) $"root:Packages:NIST:RAW:data"
910                        WAVE data=$"root:Packages:NIST:RAW:data"
911                        getDetectorData(fname,data)
912                        value = sum(data)
913                endif
914       
915        KillWaves wCounts
916       
917        return(value)
918end
919
920//Attenuator number, return 1 if your attenuators are not
921// indexed by number
922Function getAttenNumber(fname)
923        String fname
924        Variable value
925        Variable att, err
926        string dfName = ""
927               
928        err = hdfRead(fname, dfName)
929        //err not handled here
930
931        if(WaveExists($(dfName+":instrument:collimator:att")))
932                        Wave wAttrotdeg = $(dfName+":instrument:collimator:att")
933        elseif(WaveExists($(dfName+":instrument:parameters:derived_parameters:AttRotDeg")))
934                        Wave wAttrotdeg = $(dfName+":instrument:parameters:derived_parameters:AttRotDeg")
935        else
936                        print "Can't find attenuator in " + fname
937        endif   
938       
939        value = wAttrotdeg[0]
940        att = round(value)/30
941        KillWaves wAttrotdeg
942        return(att)
943end
944
945
946//transmission
947Function getSampleTrans(fname)
948        String fname
949       
950        Variable value
951       
952        // your code returning value
953        variable err
954        string dfName = ""
955        err = hdfRead(fname, dfName)
956        //err not handled here
957
958        if(WaveExists($(dfName+":reduce:Transmission"))) //canonical location
959                        Wave wTransmission = $(dfName+":reduce:Transmission")
960        elseif(WaveExists($(dfName+":instrument:parameters:Transmission")))
961                        Wave wTransmission = $(dfName+":instrument:parameters:Transmission")
962        else
963                        print "Can't find Transmission in " + fname
964        endif
965        value = wTransmission[0]
966        KillWaves wTransmission
967               
968        return(value)
969end
970
971//sample transmission (0<T<=1)
972Function WriteTransmissionToHeader(fname,trans)
973        String fname
974        Variable trans
975       
976        // your writer here
977        Wave wTransmission
978        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
979        Make /N=(1,1) wTransmission
980        String groupName = "/reduce"
981        String varName = "Transmission"
982        wTransmission[0] = trans //
983        // your code returning value
984        variable err
985        err = hdfWrite(fname, groupName, varName, wTransmission)
986        KillWaves wTransmission
987        //err not handled here
988               
989        return(0)
990End
991
992//box counts from stored transmission calculation
993// return 0 if not using NCNR transmission module
994Function getBoxCounts(fname)
995        String fname
996        Variable value
997       
998        // do nothing if not using NCNR Transmission module
999        variable err
1000        string dfName = ""
1001        err = hdfRead(fname, dfName)
1002        //err not handled here
1003
1004        Wave wBoxCounts = $(dfName+":reduce:boxCounts")
1005        if (waveexists(wBoxCounts) == 0)
1006                //boxcounts not yet set in  reduce group
1007                //return 0
1008                value = 0
1009        else
1010                value = wBoxCounts[0]
1011        endif
1012
1013        KillWaves/Z wBoxCounts
1014       
1015        return(value)
1016end
1017
1018//whole detector transmission
1019// return 0 if not using NCNR transmission module
1020Function getSampleTransWholeDetector(fname)
1021        String fname
1022        Variable value
1023       
1024        // your code returning value
1025        // ??? don't know what to put here. nha
1026        value=0
1027        return(value)
1028end
1029
1030//SampleThickness in centimeters
1031Function getSampleThickness(fname)
1032        String fname
1033        Variable value
1034
1035        // your code returning value
1036       
1037        variable err
1038        string dfName = ""
1039        err = hdfRead(fname, dfName)
1040        //err not handled here
1041
1042        if(WaveExists($(dfName+":sample:SampleThickness"))) //canonical location - a bit ugly and verbose, but that's just my opinion
1043                Wave wThickness = $(dfName+":sample:SampleThickness")
1044        elseif(WaveExists($(dfName+":sample:thickness")))
1045                Wave wThickness = $(dfName+":sample:thickness")
1046        else
1047                print "Can't find Sample Thickness in " + fname
1048        endif
1049                       
1050        value = wThickness[0]/10
1051        //value = 1 //??? temporary fix. nha
1052        KillWaves wThickness
1053       
1054        return(value)
1055end
1056
1057//sample thickness in cm
1058Function WriteThicknessToHeader(fname,thickness)
1059        String fname
1060        Variable thickness
1061       
1062        // your writer here
1063        Wave wThickness
1064        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
1065        Make /N=(1,1) wThickness
1066        String groupName = "/sample"
1067        String varName = "SampleThickness"
1068        wThickness[0] = thickness*10 //
1069        // your code returning value
1070        variable err
1071        err = hdfWrite(fname, groupName, varName, wThickness) //does not exist ???
1072        KillWaves wThickness
1073        //err not handled here
1074               
1075        return(0)
1076End
1077
1078//Sample Rotation Angle (degrees)
1079Function getSampleRotationAngle(fname)
1080        String fname
1081        Variable value
1082       
1083        // your code returning value
1084        variable err
1085        string dfName = ""
1086        err = hdfRead(fname, dfName)
1087        //err not handled here
1088
1089        Wave wSample_rotation_angle = $(dfName+":sample:sample_theta") //is this correct
1090        value = wSample_rotation_angle[0]
1091        KillWaves wSample_rotation_angle
1092               
1093        return(value)
1094end
1095
1096//temperature (C)
1097Function getTemperature(fname)
1098        String fname
1099       
1100        Variable value
1101       
1102        // your code returning value
1103       
1104        return(value)
1105end
1106
1107//field strength (Oe)
1108Function getFieldStrength(fname)
1109        String fname
1110       
1111        Variable value
1112       
1113        // your code returning value
1114       
1115        return(value)
1116end
1117
1118//center of beam xPos in pixel coordinates
1119Function getBeamXPos(fname)
1120        String fname
1121        Variable value
1122        // your code returning value
1123        variable err
1124        string dfName = ""
1125        err = hdfRead(fname, dfName)
1126        //err not handled here
1127
1128        if(WaveExists($(dfName+":instrument:reduce:BeamCenterX"))) //canonical location
1129                        Wave wBeamXPos = $(dfName+":instrument:reduce:BeamCenterX")
1130        elseif(WaveExists($(dfName+":instrument:parameters:BeamCenterX")))
1131                        Wave wBeamXPos = $(dfName+":instrument:parameters:BeamCenterX")
1132        else
1133                        print "Can't find BeamCenterX in" $fname
1134        endif
1135        value = wBeamXPos[0]   
1136        KillWaves wBeamXPos
1137       
1138        return(value)   
1139
1140end
1141
1142//beam center X pixel location (detector coordinates)
1143Function WriteBeamCenterXToHeader(fname,beamCenterX)
1144        String fname
1145        Variable beamCenterX
1146       
1147        // your writer here
1148        Wave wBeamCenterX
1149        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
1150        Make /N=(1,1) wBeamCenterX
1151        String groupName = "/instrument/reduce"
1152        String varName = "BeamCenterX"
1153        wBeamCenterX[0] = beamCenterX //
1154        // your code returning value
1155        variable err
1156        err = hdfWrite(fname, groupName, varName, wBeamCenterX)
1157        KillWaves wBeamCenterX
1158        //err not handled here
1159       
1160        return(0)
1161End
1162
1163//center of beam Y pos in pixel coordinates
1164Function getBeamYPos(fname)
1165        String fname
1166        Variable value
1167        // your code returning value
1168        variable err
1169        string dfName = ""
1170        err = hdfRead(fname, dfName)
1171        //err not handled here
1172
1173        if(WaveExists($(dfName+":instrument:reduce:BeamCenterZ"))) //canonical location
1174                        Wave wBeamYPos = $(dfName+":instrument:reduce:BeamCenterZ")
1175        elseif(WaveExists($(dfName+":instrument:parameters:BeamCenterZ")))
1176                        Wave wBeamYPos = $(dfName+":instrument:parameters:BeamCenterZ")
1177        else
1178                        print "Can't find BeamCenterZ in" $fname
1179        endif
1180        value = wBeamYPos[0]   
1181        KillWaves wBeamYPos
1182               
1183        return(value)
1184end
1185
1186//beam center Y pixel location (detector coordinates)
1187Function WriteBeamCenterYToHeader(fname,beamCenterY)
1188        String fname
1189        Variable beamCenterY
1190       
1191        // your writer here
1192        Wave wBeamCenterY
1193        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
1194        Make /N=(1,1) wBeamCenterY
1195        String groupName = "/instrument/reduce"
1196        String varName = "BeamCenterZ"
1197        wBeamCenterY[0] = beamCenterY //
1198        // your code returning value
1199        variable err
1200        err = hdfWrite(fname, groupName, varName, wBeamCenterY)
1201        KillWaves wBeamCenterY
1202        //err not handled here
1203
1204        return(0)
1205End
1206
1207
1208//sample to detector distance (meters)
1209Function getSDD(fname)
1210        String fname
1211        Variable value
1212        // your code returning value
1213        variable err
1214        string dfName = ""
1215        err = hdfRead(fname, dfName)
1216        //err not handled here
1217
1218        //workaround for bad HDF5 dataset
1219        if(WaveExists($(dfName+":instrument:parameters:L2"))) //canonical location
1220                Wave wSourceToDetectorDist = $(dfName+":instrument:parameters:L2")
1221        elseif(WaveExists($(dfName+":instrument:parameters:L2mm")))
1222                Wave wSourceToDetectorDist = $(dfName+":instrument:parameters:L2mm")
1223        elseif(WaveExists($(dfName+":instrument:parameters:derived_parameters:L2mm"))) 
1224                Wave wSourceToDetectorDist = $(dfName+":instrument:parameters:derived_parameters:L2mm")
1225        else
1226                print "Can't find L2 in " + fname
1227        endif
1228       
1229        value = wSourceToDetectorDist[0]/1000   
1230        KillWaves wSourceToDetectorDist
1231               
1232        return(value)
1233end
1234
1235//sample to detector distance (meters)
1236Function WriteSDDToHeader(fname,sdd)
1237        String fname
1238        Variable sdd
1239       
1240// your writer here
1241        Wave wSDD
1242        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
1243        Make /N=(1,1) wSDD
1244        String groupName = "/instrument/parameters"
1245        String varName = "L2"
1246        wSDD[0] = sdd * 1000 //
1247        // your code returning value
1248        variable err
1249        err = hdfWrite(fname, groupName, varName, wSDD)
1250        KillWaves wSDD
1251        //err not handled here
1252       
1253        return(0)
1254End
1255
1256//lateral detector offset (centimeters)
1257Function getDetectorOffset(fname)
1258        String fname
1259        Variable value
1260        // your code returning value
1261        variable err
1262        string dfName = ""
1263        err = hdfRead(fname, dfName)
1264        //err not handled here
1265
1266        Wave wDetectorOffset = $(dfName+":instrument:detector:detector_x") //is this correct
1267        value = wDetectorOffset[0]/10
1268        KillWaves wDetectorOffset
1269       
1270        return(value)
1271end
1272
1273//Beamstop diameter (millimeters)
1274Function getBSDiameter(fname)
1275        String fname
1276        Variable value
1277        // your code returning value
1278        variable err
1279        string dfName = ""
1280        err = hdfRead(fname, dfName)
1281        //err not handled here
1282
1283        if(WaveExists($(dfName+":instrument:parameters:BSdiam"))) //canonical location
1284                Wave wBSdiameter = $(dfName+":instrument:parameters:BSdiam")
1285        elseif(WaveExists($(dfName+":instrument:parameters:BSXmm")))
1286                Wave wBSdiameter = $(dfName+":instrument:parameters:BSXmm")
1287        else
1288                print "Can't find Beamstop Diameter in " + fname
1289        endif
1290        value = wBSdiameter[0]
1291        KillWaves wBSdiameter
1292       
1293        return(value)   
1294end
1295
1296//beam stop diameter (millimeters)
1297Function WriteBeamStopDiamToHeader(fname,bs)
1298        String fname
1299        Variable bs     
1300       
1301        // your writer here
1302        Wave wBS
1303        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
1304        Make /N=(1,1) wBS
1305        String groupName = "/instrument/parameters"
1306        String varName = "BSdiam"
1307        wBS[0] = bs //
1308        // your code returning value
1309        variable err
1310        err = hdfWrite(fname, groupName, varName, wBS)
1311        KillWaves wBS
1312        //err not handled here
1313        return(0)
1314End
1315
1316//source aperture diameter (millimeters)
1317Function getSourceApertureDiam(fname)
1318        String fname
1319        Variable value
1320        // your code returning value
1321        variable err
1322        string dfName = ""
1323        err = hdfRead(fname, dfName)
1324        //err not handled here
1325
1326        if(WaveExists($(dfName+":instrument:parameters:EApX")))
1327                Wave wSourceApertureDiam = $(dfName+":instrument:parameters:EApX") // canonical location
1328        elseif(WaveExists($(dfName+":instrument:parameters:derived_parameters:EApXmm")))
1329                Wave wSourceApertureDiam = $(dfName+":instrument:parameters:derived_parameters:EApXmm")
1330        else
1331                print "Can't find Source Aperture Diameter in " + fname
1332        endif   
1333        value = wSourceApertureDiam[0]
1334        KillWaves wSourceApertureDiam
1335       
1336        return(value)
1337end
1338
1339//Source Aperture diameter (millimeters)
1340Function WriteSourceApDiamToHeader(fname,source)
1341        String fname
1342        Variable source
1343       
1344        // your writer here
1345        Wave wsource
1346        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
1347        Make /N=(1,1) wsource
1348        String groupName = "/instrument/parameters"
1349        String varName = "EApX"
1350        wsource[0] = source //
1351        // your code returning value
1352        variable err
1353        err = hdfWrite(fname, groupName, varName, wsource)
1354        KillWaves wsource
1355        //err not handled here
1356        return(0)
1357End
1358
1359//sample aperture diameter (millimeters)
1360Function getSampleApertureDiam(fname)
1361        String fname
1362        Variable value
1363        // your code returning value
1364        variable err
1365        string dfName = ""
1366        err = hdfRead(fname, dfName)
1367        //err not handled here
1368
1369        if(WaveExists($(dfName+":sample:diameter"))) //canonical location
1370                Wave wSampleApertureDiam = $(dfName+":sample:diameter")
1371        elseif(WaveExists($(dfName+":instrument:parameters:autoSampleAp:diameter"))) //canonical location
1372                Wave wSampleApertureDiam = $(dfName+":instrument:parameters:autoSampleAp:diameter")
1373        elseif (WaveExists($(dfName+":instrument:sample_aperture:geometry:shape:SApXmm")))
1374                Wave wSampleApertureDiam = $(dfName+":instrument:sample_aperture:geometry:shape:SApXmm")
1375        else
1376                print "Can't find Sample Aperture Diameter in " + fname
1377        endif   
1378        value = wSampleApertureDiam[0]
1379        KillWaves wSampleApertureDiam
1380
1381        return(value)   
1382end
1383
1384//Sample Aperture diameter (millimeters)
1385Function WriteSampleApDiamToHeader(fname,source)
1386        String fname
1387        Variable source
1388       
1389        // your writer here
1390        Wave wsource
1391        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
1392        Make /N=(1,1) wsource
1393        String groupName = "/sample"
1394        String varName = "diameter"
1395        wsource[0] = source //
1396        // your code returning value
1397        variable err
1398        err = hdfWrite(fname, groupName, varName, wsource)
1399        KillWaves wsource
1400        //err not handled here
1401        return(0)
1402End
1403
1404//source AP to Sample AP distance (meters)
1405Function getSourceToSampleDist(fname)
1406        String fname
1407       
1408        Variable value
1409       
1410        // your code returning value
1411        variable err
1412        string dfName = ""
1413               
1414        err = hdfRead(fname, dfName)
1415        //err not handled here
1416       
1417        if(WaveExists($(dfName+":instrument:parameters:L1"))) //canonical location
1418                Wave wSourceToSampleDist = $(dfName+":instrument:parameters:L1")       
1419        elseif(WaveExists($(dfName+":instrument:parameters:L1mm")))
1420                Wave wSourceToSampleDist = $(dfName+":instrument:parameters:L1mm")
1421        elseif(WaveExists($(dfName+":instrument:parameters:derived_parameters:L1mm")))
1422                Wave wSourceToSampleDist = $(dfName+":instrument:parameters:derived_parameters:L1mm")
1423        else
1424                print "Can't find L1 in " + fname
1425        endif
1426       
1427        value = wSourceToSampleDist[0]/1000
1428        KillWaves wSourceToSampleDist   
1429               
1430        return(value)
1431end
1432
1433//Source aperture to sample aperture distance (meters)
1434Function WriteSrcToSamDistToHeader(fname,SSD)
1435        String fname
1436        Variable SSD
1437       
1438// your writer here
1439        Wave wSSD
1440        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
1441        Make /N=(1,1) wSSD
1442        String groupName = "/instrument/parameters"
1443        String varName = "L1"
1444        wSSD[0] = SSD * 1000 //input in metres, converted to mm for saving to file.
1445        // your code returning value
1446        variable err
1447        err = hdfWrite(fname, groupName, varName, wSSD)
1448        KillWaves wSSD
1449        //err not handled here
1450       
1451        return(0)
1452End
1453
1454//wavelength (Angstroms)
1455Function getWavelength(fname)
1456        String fname
1457        Variable value
1458        // your code returning value
1459        variable err
1460        string dfName = ""
1461        err = hdfRead(fname, dfName)
1462        //err not handled here
1463
1464        //      Wave wWavelength = $(dfName+":data:LambdaA")
1465        //change 22/12/09 nha
1466        // all these locations to be deprecated
1467        if(WaveExists($(dfName+":instrument:velocity_selector:Lambda")))  // canonical location
1468                Wave wWavelength = $(dfName+":instrument:velocity_selector:Lambda")
1469        elseif(WaveExists($(dfName+":data:Lambda")))
1470                Wave wWavelength = $(dfName+":data:Lambda")
1471        elseif(WaveExists($(dfName+":data:LambdaA")))
1472                Wave wWavelength = $(dfName+":data:LambdaA")
1473        elseif(WaveExists($(dfName+":instrument:velocity_selector:LambdaA")))
1474                Wave wWavelength = $(dfName+":instrument:velocity_selector:LambdaA")
1475        else
1476                print "Can't find Lambda in " + fname
1477        endif
1478        value = wWavelength[0] 
1479        KillWaves wWavelength
1480       
1481        return(value)
1482end
1483
1484//wavelength (Angstroms)
1485Function WriteWavelengthToHeader(fname,wavelength)
1486        String fname
1487        Variable wavelength
1488       
1489        // your writer here
1490        Wave wWavelength
1491        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
1492        Make /N=(1,1) wWavelength
1493        String groupName = "/instrument/velocity_selector"
1494        String varName = "Lambda"
1495        wWavelength[0] = wavelength //
1496        // your code returning value
1497        variable err
1498        err = hdfWrite(fname, groupName, varName, wWavelength)
1499       
1500        //and because Bill Hamilton is not happy with the NeXus naming, we write it to 3 other places
1501        //groupName = "/instrument/parameters"
1502        //err = hdfWrite(fname, groupName, varName, wWavelength)
1503        //velocity_selector group causes Igor crash in some cases
1504        //groupName = "/instrument/velocity_selector"
1505        //err = hdfWrite(fname, groupName, varName, wWavelength)
1506        //
1507        //groupName = "/data"
1508        //varName = "lambda"
1509        //err = hdfWrite(fname, groupName, varName, wWavelength)
1510       
1511        KillWaves wWavelength
1512        //err not handled here
1513
1514        return(0)
1515End
1516
1517
1518
1519//wavelength spread (FWHM)
1520Function getWavelengthSpread(fname)
1521        String fname
1522       
1523        Variable value
1524       
1525        // your code returning value
1526        variable err
1527        string dfName = ""
1528        err = hdfRead(fname, dfName)
1529        //err not handled here
1530       
1531        //velocity_selector group causes Igor crash
1532        if(WaveExists($(dfName+":instrument:velocity_selector:LambdaResFWHM_percent")))  //canonical location
1533                Wave wWavelengthSpread = $(dfName+":instrument:velocity_selector:LambdaResFWHM_percent")
1534        elseif(WaveExists($(dfName+":instrument:parameters:LambdaResFWHM_percent")))
1535                Wave wWavelengthSpread = $(dfName+":instrument:parameters:LambdaResFWHM_percent")
1536        else
1537                print "Can't find Wavelength Spread in " + fname
1538        endif
1539        value = wWavelengthSpread[0]   
1540        KillWaves wWavelengthSpread
1541       
1542        return(value)
1543end
1544
1545//wavelength spread (FWHM)
1546Function WriteWavelengthDistrToHeader(fname,wavelengthSpread)
1547        String fname
1548        Variable wavelengthSpread
1549       
1550        // your writer here
1551        Wave wWavelengthSpread
1552        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
1553        Make /N=(1,1) wWavelengthSpread
1554        //velocity_selector group causes Igor crash
1555        String groupName = "/instrument/velocity_selector"
1556        String varName = "LambdaResFWHM_percent"
1557
1558        wWavelengthSpread[0] = wavelengthSpread
1559        // your code returning value
1560        variable err
1561        err = hdfWrite(fname, groupName, varName, wWavelengthSpread)
1562        KillWaves wWavelengthSpread
1563        //err not handled here
1564               
1565        return(0)
1566End
1567
1568// physical x-dimension of a detector pixel, in mm
1569Function getDetectorPixelXSize(fname)
1570        String fname
1571        Variable value
1572       
1573        // your code here returning value
1574        variable err
1575        string dfName = ""
1576        err = hdfRead(fname, dfName)
1577        //err not handled here
1578
1579        Wave wActiveArea = $(dfName+":instrument:detector:active_height")
1580        Wave w_x_bin = $(dfName+":instrument:detector:x_bin")
1581        Variable numPixels = dimsize(w_x_bin, 0)
1582        value = wActiveArea[0]/numPixels
1583        KillWaves wActiveArea
1584        KillWaves w_x_bin
1585       
1586        return(value)
1587end
1588
1589// physical y-dimension of a detector pixel, in mm
1590Function getDetectorPixelYSize(fname)
1591        String fname
1592        Variable value
1593       
1594        // your code here returning value
1595        variable err
1596        string dfName = ""
1597        err = hdfRead(fname, dfName)
1598        //err not handled here
1599
1600        Wave wActiveArea = $(dfName+":instrument:detector:active_width")
1601        Wave w_y_bin = $(dfName+":instrument:detector:y_bin")
1602        Variable numPixels = dimsize(w_y_bin, 0)
1603        value = wActiveArea[0]/numPixels
1604        KillWaves wActiveArea
1605        KillWaves w_y_bin
1606                       
1607        return(value)
1608end
1609
1610//transmission detector count (unused, return 0)
1611//
1612Function getTransDetectorCounts(fname)
1613        String fname
1614       
1615        Variable value
1616       
1617        // your code returning value
1618       
1619        return(0)
1620end
1621
1622
1623//total count time (seconds)
1624Function getCountTime(fname)
1625        String fname
1626        Variable value
1627        // your code returning value
1628        variable err
1629        string dfName = ""
1630        err = hdfRead(fname, dfName)
1631        //err not handled here
1632
1633        Wave wTime1 = $(dfName+":monitor:bm1_time")
1634        value = wTime1[0]       
1635        KillWaves wTime1
1636       
1637        return(value)
1638end
1639
1640
1641Function getPhysicalWidth(fname)
1642        String fname
1643        Variable value
1644        // your code returning value
1645        variable err
1646        string dfName = ""
1647        err = hdfRead(fname, dfName)
1648        //err not handled here
1649
1650        Wave wPhysicalWidth = $(dfName+":instrument:detector:active_width")
1651        value = wPhysicalWidth[0]/10
1652        KillWaves wPhysicalWidth
1653               
1654        return(value)
1655end
1656
1657Function/S getSICSVersion(fname)
1658        String fname
1659        String value
1660        // your code returning value
1661        variable err
1662        string dfName = ""
1663        err = hdfRead(fname, dfName)
1664        //err not handled here
1665
1666        Wave/T wSICSVersion = $(dfName+":sics_release")
1667        value = wSICSVersion[0]
1668        KillWaves wSICSVersion
1669       
1670        return(value)
1671end
1672
1673Function/S getHDFversion(fname)
1674        String fname
1675        String value
1676        // your code returning value
1677        variable err
1678        string dfName = ""
1679        string attribute = "HDF5_Version"
1680        err = hdfReadAttribute(fname, dfName, "/", 1, attribute)
1681//      string attribute ="signal"
1682//      err = hdfReadAttribute(fname, dfName, "/entry/data/hmm_xy", 2, attribute)
1683        //err not handled here
1684
1685        Wave/T wHDF5_Version = $(dfName+":"+attribute)
1686        value = wHDF5_Version[0]       
1687//      KillWaves wHDF5_Version
1688
1689        return(value)
1690end
1691
1692
1693//reads the wavelength from a reduced data file (not very reliable)
1694// - does not work with NSORTed files
1695// - only used in FIT/RPA (which itself is almost NEVER used...)
1696//
1697// DOES NOT NEED TO BE CHANGED IF USING NCNR DATA WRITER
1698Function GetLambdaFromReducedData(tempName)
1699        String tempName
1700       
1701        String junkString
1702        Variable lambdaFromFile, fileVar
1703        lambdaFromFile = 6.0
1704        Open/R/P=catPathName fileVar as tempName
1705        FReadLine fileVar, junkString
1706        FReadLine fileVar, junkString
1707        FReadLine fileVar, junkString
1708        if(strsearch(LowerStr(junkString),"lambda",0) != -1)
1709                FReadLine/N=11 fileVar, junkString
1710                FReadLine/N=10 fileVar, junkString
1711                lambdaFromFile = str2num(junkString)
1712        endif
1713        Close fileVar
1714       
1715        return(lambdaFromFile)
1716End
1717
1718/////   TRANSMISSION RELATED FUNCTIONS    ////////
1719//box coordinate are returned by reference
1720//
1721// box to sum over is bounded (x1,y1) to (x2,y2)
1722//
1723// this function returns the bounding coordinates as stored in
1724// the header
1725//
1726// if not using the NCNR Transmission module, this function default to
1727// returning 0000, and no changes needed
1728Function getXYBoxFromFile(fname,x1,x2,y1,y2)
1729        String fname
1730        Variable &x1,&x2,&y1,&y2
1731       
1732        // return your bounding box coordinates or default values of 0
1733        x1=0
1734        y1=0
1735        x2=0
1736        y2=0
1737
1738        // your code returning value
1739        variable err
1740        string dfName = ""
1741        err = hdfRead(fname, dfName)
1742        //err not handled here
1743
1744       
1745        Wave wX1 = $(dfName+":reduce:x1")
1746        if (waveexists(wX1) == 0)
1747                //Waves don't exists which means an XY box has not been set for this file.
1748                //Hence return 0 bounding boxes (default)
1749        else
1750                x1 = wX1[0]
1751                Wave wX2 = $(dfName+":reduce:x2")
1752                x2 = wX2[0]
1753                Wave wY1 = $(dfName+":reduce:y1")
1754                y1 = wY1[0]
1755                Wave wY2 = $(dfName+":reduce:y2")
1756                y2 = wY2[0]
1757        endif
1758       
1759        KillWaves/Z wX1, wX2, wY1, wY2
1760        return(0)
1761
1762End
1763
1764// Writes the coordinates of the box to the header after user input
1765//
1766// box to sum over bounded (x1,y1) to (x2,y2)
1767//
1768// if not using the NCNR Transmission module, this function is null
1769Function WriteXYBoxToHeader(fname,x1,x2,y1,y2)
1770        String fname
1771        Variable x1,x2,y1,y2
1772
1773        String groupName = "/reduce"
1774        variable err
1775               
1776        Wave wX1
1777        Make/O/N=(1,1) wX1
1778        Wave wX2
1779        Make/O/N=(1,1) wX2
1780        Wave wY1
1781        Make/O/N=(1,1) wY1
1782        Wave wY2
1783        Make/O/N=(1,1) wY2
1784               
1785        wX1[0] = x1
1786        wX2[0] = x2
1787        wY1[0] = y1
1788        wY2[0] = y2     
1789       
1790        String varName = "x1"   
1791        err = hdfWrite(fname, groupName, varName,wX1)
1792        varName = "x2"
1793        err = hdfWrite(fname, groupName, varName,wX2)
1794        varName = "y1"
1795        err = hdfWrite(fname, groupName, varName,wY1)
1796        varName = "y2"
1797        err = hdfWrite(fname, groupName, varName,wY2)   
1798       
1799        KillWaves wX1,wX2,wY1,wY2
1800       
1801        //err not handled here
1802        return(0)       
1803
1804End
1805
1806// for transmission calculation, writes an NCNR-specific alphanumeric identifier
1807// (suffix of the data file)
1808//
1809//AJJ June 3 2010 - Note!! For ANSTO data the "suffix" is just the filename.
1810Function WriteAssocFileSuffixToHeader(fname,assoc_fname)
1811        String fname,assoc_fname
1812               
1813// your writer here
1814        Wave/T wAssoc_fname
1815        //nha ??? Should make this wave in our own DataFolder to avoid clashing names.
1816        Make/T /N=(1,1) wAssoc_fname
1817       
1818        String varName =""
1819        String groupName = "/reduce"
1820        if(isTransFile(fname))
1821                varName = "empty_beam_file_name"
1822        elseif(isScatFile(fname))
1823                varName = "transmission_file_name"
1824        endif
1825
1826        wAssoc_fname[0] = assoc_fname
1827        // your code returning value
1828        variable err
1829        err = hdfWrite(fname, groupName, varName, wAssoc_fname)
1830        KillWaves wAssoc_fname
1831        //err not handled here
1832        return(0)
1833end
1834
1835Function/S GetFileAssoc(fname)
1836        String fname
1837       
1838        String assoc_fname
1839        String groupName = ":reduce:"
1840       
1841        String varName = ""
1842        if(isTransFile(fname))
1843                varName = "empty_beam_file_name"
1844        elseif(isScatFile(fname))
1845                varName = "transmission_file_name"
1846        endif
1847       
1848        variable err
1849        string dfName = ""
1850        err = hdfRead(fname, dfName)
1851        //err not handled here
1852
1853        Wave/T wAssoc_fname = $(dfName+groupName+varName)
1854        if (waveexists(wAssoc_fname) == 1)
1855                assoc_fname =wAssoc_fname[0]   
1856        else
1857                assoc_fname = ""
1858        endif
1859        KillWaves/Z wAssoc_fname
1860       
1861        return(assoc_fname)
1862end
1863
1864Function hdfReadAttribute(fname, dfName, nodeName, nodeType, attributeStr)
1865// this is a copy of hdfRead, and could be incorporated back into hdfRead.
1866       
1867        String fname, &dfName, nodeName, attributeStr
1868        variable nodeType
1869        String nxentryName
1870        variable err=0,fileID   
1871        String cDF = getDataFolder(1), temp
1872        String fname_temp = ParseFilePath(0, fname, ":", 1, 0)
1873
1874       
1875        String fileSuffix
1876       
1877        if(strsearch(fname_temp,".nx.hdf",0,2)>=0)
1878                fileSuffix=".nx.hdf"
1879        else
1880                err = 1
1881                abort "unrecognised file suffix. Not .nx.hdf"
1882        endif
1883       
1884        dfName = "root:packages:quokka:"+removeending(fname_temp,fileSuffix)
1885       
1886        //folder must already exist i.e. hdfRead must have already been called
1887        if(!DataFolderExists(dfName))
1888                // possibly call an hdfRead from here
1889                return err
1890        endif
1891       
1892        //test for the name of nxentry
1893        if(DataFolderExists(dfName+":"+removeending(fname_temp,fileSuffix)))
1894                nxentryName = removeending(fname_temp,fileSuffix)
1895        elseif(DataFolderExists(dfName+":"+"entry1"))
1896                nxentryName = "entry1"
1897        else
1898                print "NXentry not found"
1899                return err
1900        endif
1901       
1902        //this is the stupid bit.
1903        // If you're looking for attributes of the root node, then nodename = "/"
1904        // If you're looking for attributes     of the nxentry node, then e.g. nodename ="/entry/instrument"
1905        // /entry is replaced with nxentryName
1906        nodeName = ReplaceString("entry", nodeName, nxentryName)       
1907       
1908        //convert nodeName to data folder string
1909        String dfNodeName = nodeName
1910        dfNodeName = ReplaceString( "/", nodeName, ":")
1911        dfName = dfName + dfNodeName
1912        if(nodeType == 2) //data item (dataset)
1913                //remove the end of dfName so that it points to a folder and not a dataset
1914                variable length = strlen(dfName)
1915                variable position = strsearch(dfName, ":", length, 1) // search backwards to find last :
1916                // to do - truncate string to remove dataset
1917                string truncate = "\"%0." + num2str(position) + "s\""
1918                sprintf dfName, truncate, dfName
1919        endif
1920       
1921        setDataFolder dfName
1922       
1923        try     
1924                HDF5OpenFile /R /Z fileID  as fname
1925                if(!fileID)
1926                        err = 1
1927                        abort "couldn't load HDF5 file"
1928                endif
1929
1930                HDF5LoadData /O /Q /Z /TYPE=(nodeType) /A=attributeStr, fileID, nodeName
1931
1932                if (V_flag!=0)
1933                        print "couldn't load attribute " + attributeStr
1934                endif
1935        catch
1936
1937        endtry
1938        if(fileID)
1939                HDF5CloseFile /Z fileID
1940        endif
1941
1942// add the name of the root node to dfName
1943// in the case of sensitivity files aka DIV files, don't append a root node to dfName
1944        if(DataFolderExists(dfName+":"+removeending(fname_temp,fileSuffix)))
1945                dfName = dfName+":"+removeending(fname_temp,fileSuffix)  //for files written Dec 2009 and after
1946        elseif(DataFolderExists(dfName+":"+"entry1"))
1947                dfName = dfName+":entry1" //for files written before Dec 2009
1948        endif
1949
1950        setDataFolder $cDF
1951        return err
1952end
1953
1954Function hdfRead(fname, dfName)
1955        //Reads hdf5 file into root:packages:quokka:fname
1956        //N. Hauser. 16/12/08
1957        // 29/1/09 - hdf file must have .nx.hdf or .div suffix
1958       
1959        String fname, &dfName
1960        variable err=0,fileID
1961        String cDF = getDataFolder(1), temp
1962        String fname_temp = ParseFilePath(0, fname, ":", 1, 0)
1963               
1964        String fileSuffix
1965        if(strsearch(fname_temp,".nx.hdf",0,2)>=0)
1966                fileSuffix=".nx.hdf"
1967        //elseif(strsearch(fname_temp,".div",0,2)>=0)
1968        //      fileSuffix=".div"
1969        else
1970                err = 1
1971                abort "unrecognised file suffix. Not .nx.hdf"
1972        endif
1973       
1974        dfName = "root:packages:quokka:"+removeending(fname_temp,fileSuffix)
1975       
1976        //if(!DataFolderExists(dfName))
1977        //      return err
1978        //else         
1979                newDataFolder /O root:packages
1980                newDataFolder /O /S root:packages:quokka
1981                newDataFolder /O /S $dfName
1982        //endif
1983       
1984        try     
1985                HDF5OpenFile /R /Z fileID  as fname
1986                if(!fileID)
1987                        err = 1
1988                        abort "couldn't load HDF5 file"
1989                endif
1990                HDF5LoadGroup /O /R /Z  :, fileID, "."
1991        catch
1992
1993        endtry
1994        if(fileID)
1995                HDF5CloseFile /Z fileID
1996        endif
1997
1998        // add the name of the root node to dfName
1999        // in the case of sensitivity files aka DIV files, don't append a root node to dfName
2000        if(DataFolderExists(dfName+":"+removeending(fname_temp,fileSuffix)))
2001                dfName = dfName+":"+removeending(fname_temp,fileSuffix)  //for files written Dec 2009 and after
2002        elseif(DataFolderExists(dfName+":"+"entry1"))
2003                dfName = dfName+":entry1" //for files written before Dec 2009
2004        endif
2005
2006        setDataFolder $cDF
2007        return err
2008end
2009
2010Function hdfWrite(fname, groupName, varName, wav)
2011        //Write Wave 'wav' to hdf5 file 'fname'
2012        //N. Hauser. nha 8/1/09
2013               
2014        String fname, groupName, varName
2015        Wave wav
2016       
2017        variable err=0, fileID,groupID
2018        String cDF = getDataFolder(1), temp
2019        String fname_temp = ParseFilePath(0, fname, ":", 1, 0)
2020        String NXentry_name
2021                       
2022        try     
2023                HDF5OpenFile/Z fileID  as fname  //open file read-write
2024                if(!fileID)
2025                        err = 1
2026                        abort "HDF5 file does not exist"
2027                endif
2028               
2029                //get the NXentry node name
2030                HDF5ListGroup /TYPE=1 fileID, "/"
2031                //remove trailing ; from S_HDF5ListGroup
2032                NXentry_name = S_HDF5ListGroup
2033                NXentry_name = ReplaceString(";",NXentry_name,"")
2034                if(strsearch(NXentry_name,":",0)!=-1) //more than one entry under the root node
2035                        err = 1
2036                        abort "More than one entry under the root node. Ambiguous"
2037                endif
2038                //concatenate NXentry node name and groupName   
2039                groupName = "/" + NXentry_name + groupName
2040                HDF5OpenGroup /Z fileID , groupName, groupID
2041
2042        //      !! At the moment, there is no entry for sample thickness in our data file
2043        //      therefore create new HDF5 group to enable write / patch command
2044        //      comment out the following group creation once thickness appears in revised file
2045       
2046                if(!groupID)
2047                        HDF5CreateGroup /Z fileID, groupName, groupID
2048                        //err = 1
2049                        //abort "HDF5 group does not exist"
2050                else
2051                        // get attributes and save them
2052                        //HDF5ListAttributes /Z fileID, groupName    this is returning null. expect it to return semicolon delimited list of attributes
2053                        //Wave attributes = S_HDF5ListAttributes
2054                endif
2055       
2056                HDF5SaveData /O /Z /IGOR=0  wav, groupID, varName
2057                if (V_flag != 0)
2058                        err = 1
2059                        abort "Cannot save wave to HDF5 dataset" + varName
2060                endif   
2061               
2062                //HDF5SaveData /O /Z /IGOR=0 /A=attributes groupID, varName
2063                //if (V_flag != 0)
2064                ////    err = 1
2065                //      abort "Cannot save attributes to HDF5 dataset"
2066                //endif
2067        catch
2068
2069        endtry
2070       
2071        if(groupID)
2072                HDF5CloseGroup /Z groupID
2073        endif
2074       
2075        if(fileID)
2076                HDF5CloseFile /Z fileID
2077        endif
2078
2079        setDataFolder $cDF
2080        return err
2081end
2082
2083Function DoEdgeCorrection(type)
2084        String type
2085        variable err = 0
2086       
2087        WAVE typeData=$("root:Packages:NIST:"+type+":data")
2088       
2089        //nha workaround for high counts on edges
2090        //copy second column to first column
2091        typeData[][0] = typeData[p][1]
2092        //copy second last column to last column
2093        typeData[][191] = typeData[p][190]
2094        //copy second row to first row
2095        typeData[0][] = typeData[1][q]
2096        //copy second last row to last row
2097        typeData[191][] = typeData[190][q]
2098       
2099        return err     
2100end
2101
2102////// OCT 2009, facility specific bits from ProDiv()
2103//"type" is the data folder that has the corrected, patched, and normalized DIV data array
2104//
2105// the header of this file is rather unimportant. Filling in a title at least would be helpful/
2106//
2107Function Write_DIV_File(type)
2108        String type
2109       
2110        // Your file writing function here. Don't try to duplicate the VAX binary format...
2111        WriteHeaderAndWork(type)
2112       
2113        return(0)
2114End
2115
2116////// OCT 2009, facility specific bits from MonteCarlo functions()
2117//"type" is the data folder that has the data array that is to be (re)written as a full
2118// data file, as if it was a raw data file
2119//
2120// not really necessary
2121//
2122Function/S Write_RawData_File(type,fullpath,dialog)
2123        String type,fullpath
2124        Variable dialog         //=1 will present dialog for name
2125       
2126        // Your file writing function here. Don't try to duplicate the VAX binary format...
2127        Print "Write_RawData_File stub"
2128       
2129        return(fullpath)
2130End
Note: See TracBrowser for help on using the repository browser.