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

Last change on this file since 740 was 726, checked in by ajj, 12 years ago

ANSTO related fix (wrong path to data)

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