source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/VSANS/V_HDF5_RW_Utils.ipf @ 1151

Last change on this file since 1151 was 1151, checked in by srkline, 3 years ago

some addtions:

DIV file generation is now aware of the High resolution detector, but the procedures are still awaiting data for testing.

Read Noise file can now be read in and stored in the (RAW) folder ReadNoise?. This is not a work folder and the data isnot changed from the RAW state. This image is then subtracted from other raw data as it is converted to a work file (SAM, EMP, etc.) Previously, only a constant value was subtracted. If the ReadNoise? data is not present, the constant will be subtracted. There is a menu option to load the ReadNoise? data.

File size: 35.9 KB
Line 
1#pragma rtGlobals=3             // Use modern global access method and strict wave access.
2
3//
4// The base functions for R/W from HDF5 files.
5// All of the specific "get" and "write" functions call these base functions which are responsible
6// for all of the open/close mechanics.
7//
8// These VSANS file-specific functions are in:
9// V_HDF5_Read.ipf
10//               and
11// V_HDF5_Write.ipf
12//
13
14// data is read into:
15//      NewDataFolder/O/S root:Packages:NIST:VSANS:RawVSANS
16// so that the data folders of the raw data won't be lying around on the top level, looking like
17// 1D data sets and interfering.
18
19
20
21// loads a raw data set into RAW, then copies into the ReadNoise folder
22// all I really need from this set is the data from the back detector, nothing else.
23Proc LoadHighResReadNoiseData()
24        V_LoadHDF5Data("","RAW")
25        V_CopyHDFToWorkFolder("RAW","ReadNoise")
26End
27
28
29
30// passing null file string presents a dialog
31Proc LoadFakeDIVData()
32        V_LoadHDF5Data("","DIV")
33End
34
35// Moved to V_MaskUtils.ipf
36// passing null file string presents a dialog
37//Proc LoadFakeMASKData()
38//      V_LoadHDF5Data("","MSK")
39//End
40
41// passing null file string presents a dialog
42Proc Read_HDF5_Raw_No_Attributes()
43        V_LoadHDF5Data("","RAW")
44End
45
46
47// TODO:
48//  x- move the initialization of the raw data folder to be in the as-yet unwritten initialization routine for
49// reduction. be sure that it's duplicated in the VCALC initialization too.
50// x- as needed, get rid of the fake redimension of the data from 3D->2D and from 128x128 to something else for VSANS
51//    This is fake since I don't have anything close to correct fake data yet. (1/29/16)
52//
53// DONE: x- is there an extra "entry" heading? Am I adding this by mistake by setting base_name="entry" for RAW data?
54//                      x- as dumb as it is -- do I just leave it now, or break everything. On the plus side, removing the extra "entry"
55//          layer may catch a lot of the hard-wired junk that is present...
56//      extra entry layer is no longer generated for any WORK folders
57//
58Function V_LoadHDF5Data(file,folder)
59        String file,folder
60
61        String base_name,detStr
62        String destPath
63        Variable ii
64       
65        destPath = "root:Packages:NIST:VSANS:"+folder
66        // before reading in new data, clean out what old data can be cleaned. hopefully new data will overwrite what is in use
67        V_KillWavesFullTree($destPath,folder,0,"",1)                    // this will traverse the whole tree, trying to kill what it can
68
69        if(DataFolderExists("root:Packages:NIST:VSANS:"+folder) == 0)           //if it was just killed?
70                NewDataFolder/O $("root:Packages:NIST:VSANS:"+folder)
71        endif
72        SetDataFolder $("root:Packages:NIST:VSANS:"+folder)
73
74        Variable err= V_LoadHDF5_NoAtt(file,folder)     // reads into current folder
75       
76        if(err)
77                DoAlert 0,"User cancelled or other file read error..."
78                return(1)
79        endif
80       
81        // if RAW data, then generate the errors and linear data copy
82        // do this 9x
83        // then do any "massaging" needed to redimension, fake values, etc.
84        //
85        string tmpStr = "root:Packages:NIST:VSANS:RAW:entry:instrument:"
86
87// if the data is DIV, then handle the data errors differently since they are already part of the data file
88// root:Packages:NIST:VSANS:DIV:entry:instrument:detector_B:
89        if(cmpstr(folder,"DIV")==0)
90                // makes data error and linear copy -- DP waves if V_MakeDataWaves_DP() called above
91                tmpStr = "root:Packages:NIST:VSANS:DIV:entry:instrument:"
92                for(ii=0;ii<ItemsInList(ksDetectorListAll);ii+=1)
93                        detStr = StringFromList(ii, ksDetectorListAll, ";")
94                        SetDataFolder $(tmpStr+"detector_"+detStr)
95                        //V_MakeDataError(tmpStr+"detector_"+detStr)   
96                        Wave data=data
97                        Duplicate/O data $(tmpStr+"detector_"+detStr+":linear_data")
98                        Wave linear_data_error=linear_data_error
99                        Duplicate/O linear_data_error $(tmpStr+"detector_"+detStr+":data_error")
100                        SetDataFolder root:
101                endfor
102        endif
103
104
105
106
107        if(cmpstr(folder,"RAW")==0)
108       
109                // TODO -- once I get "real" data, get rid of this call to force the data to be proper dimensions.
110//              V_RedimFakeData()
111               
112                V_MakeDataWaves_DP(folder)
113//              V_FakeBeamCenters()
114//              V_FakeScaleToCenter()
115               
116
117                // makes data error and linear copy -- DP waves if V_MakeDataWaves_DP() called above
118                for(ii=0;ii<ItemsInList(ksDetectorListAll);ii+=1)
119                        detStr = StringFromList(ii, ksDetectorListAll, ";")
120                        V_MakeDataError(tmpStr+"detector_"+detStr)     
121                endfor
122
123                // TODO
124                //  -- get rid of these fake calibration waves as "real" ones are filled in by NICE
125//              (currently does nothing)
126//              Execute "MakeFakeCalibrationWaves()"
127               
128                //              fMakeFakeCalibrationWaves()             //skips the alert
129
130
131                // TODO -- do I want to calculate the nonlinear x/y arrays and the q-values here?
132                // -- otherwise the mouse-over doesn't calculate the correct Q_values
133                // the display currently is not shifted or altered at all to account for the non-linearity
134                // or for display in q-values -- so why bother with this?
135                NVAR gDoNonLinearCor = root:Packages:NIST:VSANS:Globals:gDoNonLinearCor
136                // generate a distance matrix for each of the detectors
137                if (gDoNonLinearCor == 1)
138                        Print "Calculating Non-linear correction at RAW load time"// for "+ detStr
139                        for(ii=0;ii<ItemsInList(ksDetectorListNoB);ii+=1)
140                                detStr = StringFromList(ii, ksDetectorListNoB, ";")
141                                Wave w = V_getDetectorDataW(folder,detStr)
142        //                      Wave w_err = V_getDetectorDataErrW(fname,detStr)                //not here, done above w/V_MakeDataError()
143                                Wave w_calib = V_getDetTube_spatialCalib(folder,detStr)
144                                Variable tube_width = V_getDet_tubeWidth(folder,detStr)
145                                V_NonLinearCorrection(folder,w,w_calib,tube_width,detStr,destPath)
146                               
147                               
148                                //(2.4) Convert the beam center values from pixels to mm
149                                // TODO -- there needs to be a permanent location for these values??
150                                //
151                               
152                                // TODO
153                                // -- the beam center value in mm needs to be present - it is used in calculation of Qvalues
154                                // -- but having both the same is wrong...
155                                // -- the pixel value is needed for display of the panels
156                                if(kBCTR_CM)
157                                        //V_ConvertBeamCtrPix_to_mm(folder,detStr,destPath)
158                                        //
159       
160                                        Make/O/D/N=1 $(destPath + ":entry:instrument:detector_"+detStr+":beam_center_x_mm")
161                                        Make/O/D/N=1 $(destPath + ":entry:instrument:detector_"+detStr+":beam_center_y_mm")
162                                        WAVE x_mm = $(destPath + ":entry:instrument:detector_"+detStr+":beam_center_x_mm")
163                                        WAVE y_mm = $(destPath + ":entry:instrument:detector_"+detStr+":beam_center_y_mm")
164                                        x_mm[0] = V_getDet_beam_center_x(folder,detStr) * 10            // convert cm to mm
165                                        y_mm[0] = V_getDet_beam_center_y(folder,detStr) * 10            // convert cm to mm
166                                       
167                                        // TODO:::
168                                // now I need to convert the beam center in mm to pixels
169                                // and have some rational place to look for it...
170                                        V_ConvertBeamCtr_to_pix(folder,detStr,destPath)
171                                else
172                                        // beam center is in pixels, so use the old routine
173                                        V_ConvertBeamCtrPix_to_mm(folder,detStr,destPath)
174                                endif                           
175                               
176                               
177                                // (2.5) Calculate the q-values
178                                // calculating q-values can't be done unless the non-linear corrections are calculated
179                                // so go ahead and put it in this loop.
180                                // TODO :
181                                // -- make sure that everything is present before the calculation
182                                // -- beam center must be properly defined in terms of real distance
183                                // -- distances/zero location/ etc. must be clearly documented for each detector
184                                //      ** this assumes that NonLinearCorrection() has been run to generate data_RealDistX and Y
185                                // ** this routine Makes the waves QTot, qx, qy, qz in each detector folder.
186                                //
187                                V_Detector_CalcQVals(folder,detStr,destPath)
188                               
189                        endfor
190                       
191                        //"B" is handled separately
192                        //
193                        // TODO -- will "B" more naturally be defined initially in terms of pixel centers, then converted to [cm]?
194                        //
195                        detStr = "B"
196                        Wave w = V_getDetectorDataW(folder,detStr)
197                        Wave cal_x = V_getDet_cal_x(folder,detStr)
198                        Wave cal_y = V_getDet_cal_y(folder,detStr)
199               
200                        V_NonLinearCorrection_B(folder,w,cal_x,cal_y,detStr,destPath)
201
202// "B" is always naturally defined in terms of a pixel center. This can be converted to mm,
203// but the experiment will measure pixel x,y - just like ordela detectors.
204
205//                      if(kBCTR_CM)
206//
207//                              Make/O/D/N=1 $(destPath + ":entry:instrument:detector_"+detStr+":beam_center_x_mm")
208//                              Make/O/D/N=1 $(destPath + ":entry:instrument:detector_"+detStr+":beam_center_y_mm")
209//                              WAVE x_mm = $(destPath + ":entry:instrument:detector_"+detStr+":beam_center_x_mm")
210//                              WAVE y_mm = $(destPath + ":entry:instrument:detector_"+detStr+":beam_center_y_mm")
211//                              x_mm[0] = V_getDet_beam_center_x(folder,detStr) * 10            // convert cm to mm
212//                              y_mm[0] = V_getDet_beam_center_y(folder,detStr) * 10            // convert cm to mm
213//                             
214//                              // now I need to convert the beam center in mm to pixels
215//                              // and have some rational place to look for it...
216//                              V_ConvertBeamCtr_to_pixB(folder,detStr,destPath)
217//                      else
218
219                                // beam center is in pixels, so use the old routine
220                                V_ConvertBeamCtrPix_to_mmB(folder,detStr,destPath)
221
222//                      endif
223                        V_Detector_CalcQVals(folder,detStr,destPath)
224
225                else
226                        Print "Non-linear correction not done"
227                endif
228                                       
229
230// shift the detector image on the back detector to get the three CCD images to match up
231// in real space. the distance matrices x and y still apply. be sure to mask out the chunks
232// that were lost in the shift
233
234                // the data wave is altered
235                // the linear_data wave is not altered
236                               
237                Wave adjW = V_getDetectorDataW(folder,"B")
238                Wave w = V_getDetectorLinearDataW(folder,"B")
239                V_ShiftBackDetImage(w,adjW)
240
241// and repeat for the error wave
242                Wave adjW = V_getDetectorDataErrW(folder,"B")
243                Wave w = V_getDetectorLinearDataErrW(folder,"B")
244                V_ShiftBackDetImage(w,adjW)
245               
246               
247                                                       
248                /// END DATA CORRECTIONS FOR LOADER     
249                       
250        endif
251       
252        SetDataFolder root:
253        return(err)
254End
255
256// fname is the folder = "RAW"
257Function V_MakeDataWaves_DP(fname)
258        String fname
259       
260        Variable ii
261        String detStr
262       
263        for(ii=0;ii<ItemsInList(ksDetectorListAll);ii+=1)
264                detStr = StringFromList(ii, ksDetectorListAll, ";")
265                Wave w = V_getDetectorDataW(fname,detStr)
266//              Wave w_err = V_getDetectorDataErrW(fname,detStr)  //not here, done in V_MakeDataError() by duplicating dataW
267                Redimension/D w
268//              Redimension/D w_err
269        endfor
270       
271        return(0)
272End
273
274
275
276//
277// TODO -- this is all FAKED since all the data arrays are written to hdf as (1,128,128)
278//  -- try to fill in the bits from VCALC, if it exists (or force it)
279//
280// the SetScale parts may be useful later.
281//
282// This is NOT CALLED anymore.
283// the rescaling (SetScale) of the data sets is still done separately to a "fake" beam center
284Function xV_RedimFakeData()
285       
286        // check for fake data in VCALC folder...
287        wave/Z tmpw=$"root:Packages:NIST:VSANS:VCALC:entry:instrument:detector_B:det_B"
288        if(WaveExists(tmpw) == 0)
289                Execute "VCALC_Panel()"
290        endif
291       
292        SetDataFolder root:Packages:NIST:VSANS:RAW:entry:instrument:detector_B
293        Wave det_B=data
294//      Redimension/N=(150,150)/E=1 det_B       
295        Redimension/D det_B
296        wave tmpw=$"root:Packages:NIST:VSANS:VCALC:entry:instrument:detector_B:det_B"
297//      det_B=tmpw
298//      det_B += 2
299        Wave distance=distance
300        distance = VC_getSDD("B")*100           // to convert m to cm
301
302                       
303        Variable ctr=20,npix=128
304        SetDataFolder root:Packages:NIST:VSANS:RAW:entry:instrument:detector_MT
305        Wave det_MT=data
306//      Redimension/N=(npix,48)/E=1 det_MT
307        Redimension/D det_MT           
308        SetScale/I x -npix/2,npix/2,"",det_MT
309        SetScale/I y ctr,ctr+48,"",det_MT
310//      det_MT *= 10
311//      det_MT += 2
312        wave tmpw=$"root:Packages:NIST:VSANS:VCALC:entry:instrument:detector_MT:det_MT"
313//      det_MT=tmpw
314//      det_MT += 2
315        Wave distance=distance
316        distance = VC_getSDD("MT")*100          // to convert m to cm
317
318       
319        SetDataFolder root:Packages:NIST:VSANS:RAW:entry:instrument:detector_MB
320        Wave det_MB=data
321//      Redimension/N=(npix,48)/E=1 det_MB             
322        Redimension/D det_MB
323        SetScale/I x -npix/2,npix/2,"",det_MB
324        SetScale/I y -ctr-48,-ctr,"",det_MB
325//      det_MB *= 5
326//      det_MB += 2
327        wave tmpw=$"root:Packages:NIST:VSANS:VCALC:entry:instrument:detector_MB:det_MB"
328//      det_MB=tmpw
329//      det_MB += 2
330        Wave distance=distance
331        distance = VC_getSDD("MB")*100          // to convert m to cm
332
333       
334        ctr=30
335        SetDataFolder root:Packages:NIST:VSANS:RAW:entry:instrument:detector_ML
336        Wave det_ML=data
337//      Redimension/N=(48,npix)/E=1 det_ML             
338        Redimension/D det_ML
339        SetScale/I x -ctr-48,-ctr,"",det_ML
340        SetScale/I y -npix/2,npix/2,"",det_ML
341//      det_ML *= 2
342//      det_ML += 2
343        wave tmpw=$"root:Packages:NIST:VSANS:VCALC:entry:instrument:detector_ML:det_ML"
344//      det_ML=tmpw
345//      det_ML += 2
346        Wave distance=distance
347        distance = VC_getSDD("ML")*100          // to convert m to cm
348
349               
350        SetDataFolder root:Packages:NIST:VSANS:RAW:entry:instrument:detector_MR
351        Wave det_MR=data
352//      Redimension/N=(48,npix)/E=1 det_MR             
353        Redimension/D det_MR
354        SetScale/I x ctr,ctr+48,"",det_MR
355        SetScale/I y -npix/2,npix/2,"",det_MR
356//      det_MR +=2
357        wave tmpw=$"root:Packages:NIST:VSANS:VCALC:entry:instrument:detector_MR:det_MR"
358//      det_MR=tmpw
359//      det_MR += 2
360        Wave distance=distance
361        distance = VC_getSDD("MR")*100          // to convert m to cm
362       
363       
364        ctr=30
365        SetDataFolder root:Packages:NIST:VSANS:RAW:entry:instrument:detector_FT
366        Wave det_FT=data
367//      Redimension/N=(npix,48)/E=1 det_FT             
368        Redimension/D det_FT
369        SetScale/I x -npix/2,npix/2,"",det_FT
370        SetScale/I y ctr,ctr+48,"",det_FT
371        wave tmpw=$"root:Packages:NIST:VSANS:VCALC:entry:instrument:detector_FT:det_FT"
372//      det_FT=tmpw
373        Wave distance=distance
374        distance = VC_getSDD("FT")*100          // to convert m to cm
375
376
377        SetDataFolder root:Packages:NIST:VSANS:RAW:entry:instrument:detector_FB
378        Wave det_FB=data
379//      Redimension/N=(npix,48)/E=1 det_FB             
380        Redimension/D det_FB
381        SetScale/I x -npix/2,npix/2,"",det_FB
382        SetScale/I y -ctr-48,-ctr,"",det_FB
383        wave tmpw=$"root:Packages:NIST:VSANS:VCALC:entry:instrument:detector_FB:det_FB"
384//      det_FB=tmpw
385        Wave distance=distance
386        distance = VC_getSDD("FB")*100          // to convert m to cm
387
388                       
389        SetDataFolder root:Packages:NIST:VSANS:RAW:entry:instrument:detector_FL
390        Wave det_FL=data
391//      Redimension/N=(48,npix)/E=1 det_FL             
392        Redimension/D det_FL
393        SetScale/I x -ctr-48,-ctr,"",det_FL
394        SetScale/I y -npix/2,npix/2,"",det_FL
395        wave tmpw=$"root:Packages:NIST:VSANS:VCALC:entry:instrument:detector_FL:det_FL"
396//      det_FL=tmpw
397        Wave distance=distance
398        distance = VC_getSDD("FL")*100          // to convert m to cm
399
400       
401        SetDataFolder root:Packages:NIST:VSANS:RAW:entry:instrument:detector_FR
402        Wave det_FR=data
403//      Redimension/N=(48,npix)/E=1 det_FR             
404        Redimension/D det_FR
405        SetScale/I x ctr,ctr+48,"",det_FR
406        SetScale/I y -npix/2,npix/2,"",det_FR
407        wave tmpw=$"root:Packages:NIST:VSANS:VCALC:entry:instrument:detector_FR:det_FR"
408//      det_FR=tmpw
409        Wave distance=distance
410        distance = VC_getSDD("FR")*100          // to convert m to cm
411
412       
413// get rid of zeros
414//      det_FL += 2
415//      det_FR += 2
416//      det_FT += 2
417//      det_FB += 2
418
419
420// fake beam center values
421        V_putDet_beam_center_x("RAW","B",75)
422        V_putDet_beam_center_y("RAW","B",75)
423
424        V_putDet_beam_center_x("RAW","MB",64)
425        V_putDet_beam_center_y("RAW","MB",55)
426        V_putDet_beam_center_x("RAW","MT",64)
427        V_putDet_beam_center_y("RAW","MT",-8.7)
428        V_putDet_beam_center_x("RAW","MR",-8.1)
429        V_putDet_beam_center_y("RAW","MR",64)
430        V_putDet_beam_center_x("RAW","ML",55)
431        V_putDet_beam_center_y("RAW","ML",64)
432
433        V_putDet_beam_center_x("RAW","FB",64)
434        V_putDet_beam_center_y("RAW","FB",55)
435        V_putDet_beam_center_x("RAW","FT",64)
436        V_putDet_beam_center_y("RAW","FT",-8.7)
437        V_putDet_beam_center_x("RAW","FR",-8.1)
438        V_putDet_beam_center_y("RAW","FR",64)
439        V_putDet_beam_center_x("RAW","FL",55)
440        V_putDet_beam_center_y("RAW","FL",64)
441
442
443        V_RescaleToBeamCenter("RAW","MB",64,55)
444        V_RescaleToBeamCenter("RAW","MT",64,-8.7)
445        V_RescaleToBeamCenter("RAW","MR",-8.1,64)
446        V_RescaleToBeamCenter("RAW","ML",55,64)
447        V_RescaleToBeamCenter("RAW","FL",55,64)
448        V_RescaleToBeamCenter("RAW","FR",-8.1,64)
449        V_RescaleToBeamCenter("RAW","FT",64,-8.7)
450        V_RescaleToBeamCenter("RAW","FB",64,55)
451
452
453
454        return(0)
455End
456
457
458// This loads for speed, since loading the attributes takes a LOT of time.
459//
460// this will load in the whole HDF file all at once.
461// Attributes are NOT loaded at all.
462//
463// -- the Gateway function H5GW_ReadHDF5(parentFolder, fileName, [hdf5Path])
464//    reads in the attributes too, but is very slow
465//   -- the H5GW function is called by: H_HDF5Gate_Read_Raw(file)
466//
467// TODO:
468// -x remove the P=home restriction top make this more generic (replaced with catPathName from PickPath)
469// -- get rid of bits leftover here that I don't need
470// -- be sure I'm using all of the correct flags in the HDF5LoadGroup operation
471// -- settle on how the base_name is to be used. "entry" for the RAW, fileName for the "rawVSANS"?
472// x- error check for path existence
473//
474// passing in "" for base_name will take the name from the file name as selected
475//
476Function V_LoadHDF5_NoAtt(fileName,base_name)
477        String fileName, base_name
478       
479//      if ( ParamIsDefault(hdf5Path) )
480//              hdf5Path = "/"
481//      endif
482
483        PathInfo/S catPathName
484        if(V_flag == 0)
485                DoAlert 0,"Pick the data folder, then the data file"
486                V_PickPath()
487        endif
488
489        String hdf5path = "/"           //always read from the top
490        String status = ""
491
492        Variable fileID = 0
493//      HDF5OpenFile/R/P=home/Z fileID as fileName              //read file from home directory?
494        HDF5OpenFile/R/P=catPathName/Z fileID as fileName
495        if (V_Flag != 0)
496                return 1
497        endif
498
499        String/G root:file_path = S_path
500        String/G root:file_name = S_FileName
501       
502        if ( fileID == 0 )
503                Print fileName + ": could not open as HDF5 file"
504                return (1)
505        endif
506       
507//v_tic()               //fast
508       
509        SVAR tmpStr=root:file_name
510        fileName=tmpStr         //SRK - in case the file was chosen from a dialog, I'll need access to the name later
511       
512        //   read the data (too bad that HDF5LoadGroup does not read the attributes)
513//      if(cmpstr(base_name,"") == 0)
514//              base_name = StringFromList(0,FileName,".")
515//      endif
516       
517        // if base_name is from my list of WORK folders + RawVSANS;, then base_name = ""
518        // use a stringSwitch? WhichListItem?
519        Variable isFolder = WhichListItem(base_name,ksWorkFolderListShort+"RawVSANS;")
520        if(isFolder != -1)
521                base_name = ""
522        else
523                base_name = StringFromList(0,FileName,".")              // just the first part of the name, no .nxs.ngv
524        endif
525
526
527// TODO
528// -- write a separate function or add a flag to this one that will read everything, including the DAS_logs
529//   -- the DAS_logs are not needed for reduction, and slow everything down a LOT (0.6 s per file vs 0.04 s per file!)
530
531//
532//// loads everything with one line      (includes /DAS_logs)
533//      HDF5LoadGroup/Z/L=7/O/R/T=$base_name  :, fileID, hdf5Path               //      recursive
534//
535
536// ***NOTE***
537// The temperature block definitons inculde dupilcated groups. As of 7/27/17 (HDF 5 XOP version 1.24, in Igor 7.05)
538// these duplicated blocks are now handled "correctly" by reading in the multiple copies into
539// duplciated data folders. WM (Howard) modifed the XOP to accomodate this condition.
540// This is the R=2 flag for HDF5LoadGroup
541
542//// to skip DAS_logs. I need to generate all of the data folders myself
543//// must be an easier way to handle the different path syntax, but at least this works
544
545        String curDF = GetDataFolder(1)
546
547// load root/entry
548        hdf5path = "/entry"
549//      NewDataFolder/O $(curDF)
550        if(isFolder == -1)
551                NewDataFolder/O $(curDF+base_name)
552        endif
553        if(isFolder == -1)
554                NewDataFolder/O/S $(curDF+base_name+":entry")
555        else
556                // base_name is "", so get rid of the leading ":" on ":entry"
557                NewDataFolder/O/S $(curDF+base_name+"entry")
558        endif
559        HDF5LoadGroup/Z/L=7/O :, fileID, hdf5Path               //      NOT recursive
560
561
562        if(isFolder == -1)
563                NewDataFolder/O/S $(curDF+base_name+":entry:control")
564        else
565                NewDataFolder/O/S $(curDF+base_name+"entry:control")
566        endif
567        hdf5path = "/entry/control"
568        HDF5LoadGroup/Z/L=7/O/R=2  :, fileID, hdf5Path          //      YES recursive
569
570        if(isFolder == -1)
571                NewDataFolder/O/S $(curDF+base_name+":entry:instrument")
572        else
573                NewDataFolder/O/S $(curDF+base_name+"entry:instrument")
574        endif
575        hdf5path = "/entry/instrument"
576        HDF5LoadGroup/Z/L=7/O/R=2  :, fileID, hdf5Path          //      YES recursive
577
578        if(isFolder == -1)
579                NewDataFolder/O/S $(curDF+base_name+":entry:reduction")
580        else
581                NewDataFolder/O/S $(curDF+base_name+"entry:reduction")
582        endif   
583        hdf5path = "/entry/reduction"
584        HDF5LoadGroup/Z/L=7/O/R=2  :, fileID, hdf5Path          //      YES recursive
585
586        if(isFolder == -1)
587                NewDataFolder/O/S $(curDF+base_name+":entry:sample")
588        else
589                NewDataFolder/O/S $(curDF+base_name+"entry:sample")
590        endif   
591        hdf5path = "/entry/sample"
592        HDF5LoadGroup/Z/L=7/O/R=2  :, fileID, hdf5Path          //      YES recursive (This is the only one that may have duplicated groups)
593
594        if(isFolder == -1)
595                NewDataFolder/O/S $(curDF+base_name+":entry:user")
596        else
597                NewDataFolder/O/S $(curDF+base_name+"entry:user")
598        endif   
599        hdf5path = "/entry/user"
600        HDF5LoadGroup/Z/L=7/O/R=2  :, fileID, hdf5Path          //      YES recursive
601
602
603       
604        if ( V_Flag != 0 )
605                Print fileName + ": could not open as HDF5 file"
606                setdatafolder root:
607                return (1)
608        endif
609
610        HDF5CloseFile fileID
611       
612//v_toc()
613
614        // save a global string with the file name to be picked up for the status on the display
615        // this string can be carried around as the data is moved to other folders
616//      Print curDF+"gFileList"
617        String/G $(curDF+"gFileList") = fileName
618
619
620        SetDataFolder root:
621       
622        return(0)
623end     
624
625
626// read a single real value
627// - fname passed in is the full path to the file on disk --OR-- a WORK folder
628// - path is the path to the value in the HDF tree
629//
630/// -- if data requested from a WORK or VCALC folder:
631// check to see if the value exists (It will be a wave)
632// -- if it does, return the value from the local WORK folder
633//              if it does not exist, return DUMMY value
634//
635//// -- if data requested from a file:
636// check to see if the value exists locally in RawVSANS (It will be a wave)
637// -- if it does, return the value from the local folder
638// -- if not, read the file in, then return the value
639//
640//
641Function V_getRealValueFromHDF5(fname,path)
642        String fname,path
643
644        String folderStr=""
645        Variable valExists=0
646        Variable errorValue = -999999
647       
648        folderStr = V_RemoveDotExtension(V_GetFileNameFromPathNoSemi(fname))
649
650// (1) if requesting data from a WORK folder, get it, or report error
651        Variable isWORKFolder = WhichListItem(fname,ksWorkFolderListShort+"VCALC;RealTime;")
652        if(isWORKFolder != -1)          //requesting value from a WORK folder (not RawVSANS)
653        // check for a work folder first (note that "entry" is now NOT doubled)
654                if(Exists("root:Packages:NIST:VSANS:"+folderStr+":"+path))
655                        Wave/Z w = $("root:Packages:NIST:VSANS:"+folderStr+":"+path)
656                        return(w[0])
657                else
658                        return(errorValue)
659                endif
660        endif
661
662
663        // (2) requesting from a file.
664        // look locally in RawVSANS if possible, or if not, load in the data from disk
665        // - if thee both fail, report an error
666        if(Exists(ksBaseDFPath+folderStr+":"+path))
667                valExists=1
668        endif
669       
670        if(!valExists)
671                //then read in the file, putting the data in RawVSANS
672                SetDataFolder ksBaseDFPath
673                V_LoadHDF5_NoAtt(fname,"")
674                SetDataFolder root:
675        endif
676
677// this should exist now - if not, I need to see the error
678        Wave/Z w = $(ksBaseDFPath+folderStr+":"+path)
679       
680        if(WaveExists(w))
681                return(w[0])
682        else
683                return(errorValue)
684        endif   
685End
686
687// Returns a wave reference, not just a single value
688// ---then you pick what you need from the wave
689//
690// - fname passed in is the full path to the file on disk
691// - path is the path to the value in the HDF tree
692//
693// check to see if the value exists (It will be a wave)
694// -- if it does, return the value from the local folder
695// -- if not, read the file in, then return the value
696//
697// if the wave is null, then that is returned, and the calling function is responsible
698//
699Function/WAVE V_getRealWaveFromHDF5(fname,path)
700        String fname,path
701
702        String folderStr=""
703        Variable valExists=0
704       
705        folderStr = V_RemoveDotExtension(V_GetFileNameFromPathNoSemi(fname))
706
707// (1) if requesting data from a WORK folder, get it
708// no need to check for any existence, null return is OK
709        Variable isWORKFolder = WhichListItem(fname,ksWorkFolderListShort+"VCALC;RealTime;")
710        if(isWORKFolder != -1)          //requesting value from a WORK folder (not RawVSANS)
711//      // check for a work folder first (note that "entry" is now NOT doubled)
712//              if(Exists("root:Packages:NIST:VSANS:"+folderStr+":"+path))
713                        Wave/Z wOut = $("root:Packages:NIST:VSANS:"+folderStr+":"+path)
714                        return wOut
715        endif
716
717//// check for a work folder first (note that "entry" is NOT doubled)
718//      if(Exists("root:Packages:NIST:VSANS:"+folderStr+":"+path))
719//              Wave wOut = $("root:Packages:NIST:VSANS:"+folderStr+":"+path)
720//              return wOut
721//      endif
722       
723// (2) requesting from a file
724        if(Exists(ksBaseDFPath+folderStr+":"+path))
725                valExists=1
726        endif
727
728        if(!valExists)
729                //then read in the file, putting the data in RawVSANS
730                SetDataFolder ksBaseDFPath
731                V_LoadHDF5_NoAtt(fname,"")
732                SetDataFolder root:
733        endif
734               
735// this should exist now - if not, I need to see the error
736        Wave wOut = $(ksBaseDFPath+folderStr+":"+path)
737       
738        return wOut
739       
740End
741
742// Returns a wave reference, not just a single value
743// ---then you pick what you need from the wave
744//
745// - fname passed in is the full path to the file on disk
746// - path is the path to the value in the HDF tree
747//
748// check to see if the value exists (It will be a wave)
749// -- if it does, return the value from the local folder
750// -- if not, read the file in, then return the value
751//
752// if the wave is null, then that is returned, and the calling function is responsible
753//
754Function/WAVE V_getTextWaveFromHDF5(fname,path)
755        String fname,path
756
757        String folderStr=""
758        Variable valExists=0
759       
760        folderStr = V_RemoveDotExtension(V_GetFileNameFromPathNoSemi(fname))
761
762// (1) if requesting data from a WORK folder, get it
763// no need to check for any existence, null return is OK
764        Variable isWORKFolder = WhichListItem(fname,ksWorkFolderListShort+"VCALC;RealTime;")
765        if(isWORKFolder != -1)          //requesting value from a WORK folder (not RawVSANS)
766//      // check for a work folder first (note that "entry" is now NOT doubled)
767//              if(Exists("root:Packages:NIST:VSANS:"+folderStr+":"+path))
768                        Wave/Z/T wOut = $("root:Packages:NIST:VSANS:"+folderStr+":"+path)
769                        return wOut
770        endif
771       
772//// check for a work folder first (note that "entry" is NOT doubled)
773//      if(Exists("root:Packages:NIST:VSANS:"+folderStr+":"+path))
774//              Wave/T wOut = $("root:Packages:NIST:VSANS:"+folderStr+":"+path)
775//              return wOut
776//      endif
777
778// (2) requesting from a file   
779        if(Exists(ksBaseDFPath+folderStr+":"+path))
780                valExists=1
781        endif
782       
783        if(!valExists)
784                //then read in the file, putting the data in RawVSANS
785                SetDataFolder ksBaseDFPath
786                V_LoadHDF5_NoAtt(fname,"")
787                SetDataFolder root:
788        endif
789
790// this should exist now - if not, I will see the error in the calling function
791        Wave/T/Z wOut = $(ksBaseDFPath+folderStr+":"+path)
792       
793        return wOut
794       
795End
796
797
798//
799//   TODO
800// depricated? in HDF5 - store all of the values as real?
801// Igor sees no difference in real and integer variables (waves are different)
802// BUT-- Igor 7 will have integer variables
803//
804// truncate to integer before returning??
805//
806//  TODO
807// write a "getIntegerWave" function??
808//
809//////  integer values
810// reads 32 bit integer
811Function V_getIntegerFromHDF5(fname,path)
812        String fname                            //full path+name
813        String path                             //path to the hdf5 location
814       
815        Variable val = V_getRealValueFromHDF5(fname,path)
816       
817        val = round(val)
818        return(val)
819End
820
821
822// read a single string
823// - fname passed in is the full path to the file on disk --OR-- a WORK folder
824// - path is the path to the value in the HDF tree
825// - num is the number of characters in the VAX string
826//
827/// -- if data requested from a WORK or VCALC folder:
828// check to see if the value exists (It will be a wave)
829// -- if it does, return the value from the local WORK folder
830//              if it does not exist, return DUMMY value
831//
832//// -- if data requested from a file:
833// check to see if the value exists locally in RawVSANS (It will be a wave)
834// -- if it does, return the value from the local folder
835// -- if not, read the file in, then return the value
836//
837// TODO -- string could be checked for length, but returned right or wrong
838//
839// -- currently num is completely ignored
840//
841Function/S V_getStringFromHDF5(fname,path,num)
842        String fname,path
843        Variable num
844
845        String folderStr=""
846        Variable valExists=0
847        String errorString = "The specified wave does not exist: " + path
848       
849        folderStr = V_RemoveDotExtension(V_GetFileNameFromPathNoSemi(fname))
850
851// (1) if requesting data from a WORK folder, get it, or report error
852        Variable isWORKFolder = WhichListItem(fname,ksWorkFolderListShort+"VCALC;RealTime;")
853        if(isWORKFolder != -1)          //requesting value from a WORK folder (not RawVSANS)
854        // check for a work folder first (note that "entry" is now NOT doubled)
855                if(Exists("root:Packages:NIST:VSANS:"+folderStr+":"+path))
856                        Wave/Z/T tw = $("root:Packages:NIST:VSANS:"+folderStr+":"+path)
857                        return(tw[0])
858                else
859                        return(errorSTring)
860                endif
861        endif
862
863// (2) requesting from a file.
864// look locally in RawVSANS if possible, or if not, load in the data from disk
865// - if thee both fail, report an error
866        if(Exists(ksBaseDFPath+folderStr+":"+path))
867                valExists=1
868        endif
869
870        if(!valExists)
871                //then read in the file, putting the data in RawVSANS
872                SetDataFolder ksBaseDFPath
873                V_LoadHDF5_NoAtt(fname,"")
874                SetDataFolder root:
875        endif
876
877// this should exist now - if not, I need to see the error
878        Wave/T/Z tw = $(ksBaseDFPath+folderStr+":"+path)
879       
880        if(WaveExists(tw))
881       
882        //      if(strlen(tw[0]) != num)
883        //              Print "string is not the specified length"
884        //      endif
885               
886                return(tw[0])
887        else
888                return(errorString)
889        endif
890End
891
892
893
894///////////////////////////////
895
896//
897//Write Wave 'wav' to hdf5 file 'fname'
898//Based on code from ANSTO (N. Hauser. nha 8/1/09)
899//
900// TODO:
901// -- figure out if this will write in the native format of the
902//     wave as passed in, or if it will only write as DP.
903// -- do I need to write separate functions for real, integer, etc.?
904// -- the lines to create a missing group have been commented out to avoid filling
905//    in missing fields that should have been generated by the data writer. Need to make
906//    a separate function that will write and generate if needed, and use this in specific cases
907//    only if I really have to force it.
908//
909// --Attributes are not currently saved. Fix this, maybe make it optional? See the help file for
910//  DemoAttributes(w) example under the HDF5SaveData operation
911//     
912// -x change the /P=home to the user-defined data path (catPathName)           
913//
914Function V_WriteWaveToHDF(fname, groupName, varName, wav)
915        String fname, groupName, varName
916        Wave wav
917       
918       
919        // try a local folder first, then try to save to disk
920        //
921        String folderStr = V_RemoveDotExtension(V_GetFileNameFromPathNoSemi(fname))
922       
923        String localPath = "root:Packages:NIST:VSANS:"+folderStr//+":entry"
924        localPath += groupName + "/" + varName
925        // make everything colons for local data folders
926        localPath = ReplaceString("/", localPath, ":")
927       
928        Wave/Z w = $localPath
929        if(waveExists(w) == 1)
930                w = wav
931//              Print "write to local folder done"
932                return(0)               //we're done, get out
933        endif
934       
935       
936        // if the local wave did not exist, then we proceed to write to disk
937
938       
939        variable err=0, fileID,groupID
940        String cDF = getDataFolder(1), temp
941        String NXentry_name
942       
943        try     
944                HDF5OpenFile/P=catPathName /Z fileID  as fname  //open file read-write
945                if(!fileID)
946                        err = 1
947                        abort "HDF5 file does not exist"
948                endif
949               
950                //get the NXentry node name
951                HDF5ListGroup /TYPE=1 fileID, "/"
952                //remove trailing ; from S_HDF5ListGroup
953               
954                Print "S_HDF5ListGroup = ",S_HDF5ListGroup
955               
956                NXentry_name = S_HDF5ListGroup
957                NXentry_name = ReplaceString(";",NXentry_name,"")
958                if(strsearch(NXentry_name,":",0)!=-1) //more than one entry under the root node
959                        err = 1
960                        abort "More than one entry under the root node. Ambiguous"
961                endif
962                //concatenate NXentry node name and groupName   
963                // SRK - NOV2015 - dropped this and require the full group name passed in
964//              groupName = "/" + NXentry_name + groupName
965                Print "groupName = ",groupName
966                HDF5OpenGroup /Z fileID , groupName, groupID
967
968                if(!groupID)
969                // don't create the group if the name isn't right -- throw up an error
970                        //HDF5CreateGroup /Z fileID, groupName, groupID
971                        err = 1
972                        HDF5CloseFile /Z fileID
973                        DoAlert 0, "HDF5 group does not exist "+groupName+varname
974                        return(err)
975                else
976                        // get attributes and save them
977                        //HDF5ListAttributes /Z fileID, groupName    this is returning null. expect it to return semicolon delimited list of attributes
978                        //Wave attributes = S_HDF5ListAttributes
979                endif
980       
981                HDF5SaveData /O /Z /IGOR=0 wav, groupID, varName
982                if (V_flag != 0)
983                        err = 1
984                        abort "Cannot save wave to HDF5 dataset " + varName
985                endif   
986               
987               
988                //attributes - something could be added here as optional parameters and flagged
989//              String attributes = "units"
990//              Make/O/T/N=1 tmp
991//              tmp[0] = "dimensionless"
992//              HDF5SaveData /O /Z /IGOR=0 /A=attributes tmp, groupID, varName
993//              if (V_flag != 0)
994//                      err = 1
995//                      abort "Cannot save attributes to HDF5 dataset"
996//              endif   
997        catch
998
999        endtry
1000
1001// it is not necessary to close the group here. HDF5CloseFile will close the group as well     
1002        if(groupID)
1003                HDF5CloseGroup /Z groupID
1004        endif
1005       
1006        if(fileID)
1007                HDF5CloseFile /Z fileID
1008        endif
1009
1010        setDataFolder $cDF
1011        return err
1012end
1013
1014//Write Wave 'wav' to hdf5 file 'fname'
1015//Based on code from ANSTO (N. Hauser. nha 8/1/09)
1016//
1017// TODO
1018//
1019// -x change the /P=home to the user-defined data path (catPathName)           
1020//
1021Function V_WriteTextWaveToHDF(fname, groupName, varName, wav)
1022        String fname, groupName, varName
1023        Wave/T wav
1024
1025        // try a local folder first, then try to save to disk
1026        //
1027        String folderStr = V_RemoveDotExtension(V_GetFileNameFromPathNoSemi(fname))
1028       
1029        String localPath = "root:Packages:NIST:VSANS:"+folderStr//+":entry"
1030        localPath += groupName + "/" + varName
1031        // make everything colons for local data folders
1032        localPath = ReplaceString("/", localPath, ":")
1033       
1034        Wave/Z/T w = $localPath
1035        if(waveExists(w) == 1)
1036                w = wav
1037                Print "write to local folder done"
1038                return(0)               //we're done, get out
1039        endif
1040       
1041       
1042        // if the local wave did not exist, then we proceed to write to disk
1043
1044
1045       
1046        variable err=0, fileID,groupID
1047        String cDF = getDataFolder(1), temp
1048        String NXentry_name
1049       
1050        try     
1051                HDF5OpenFile/P=catPathName /Z fileID  as fname  //open file read-write
1052                if(!fileID)
1053                        err = 1
1054                        abort "HDF5 file does not exist"
1055                endif
1056               
1057                //get the NXentry node name
1058                HDF5ListGroup /TYPE=1 fileID, "/"
1059                //remove trailing ; from S_HDF5ListGroup
1060               
1061                Print "S_HDF5ListGroup = ",S_HDF5ListGroup
1062               
1063                NXentry_name = S_HDF5ListGroup
1064                NXentry_name = ReplaceString(";",NXentry_name,"")
1065                if(strsearch(NXentry_name,":",0)!=-1) //more than one entry under the root node
1066                        err = 1
1067                        abort "More than one entry under the root node. Ambiguous"
1068                endif
1069
1070                //concatenate NXentry node name and groupName
1071                // SRK - NOV2015 - dropped this and require the full group name passed in
1072//              groupName = "/" + NXentry_name + groupName
1073                Print "groupName = ",groupName
1074
1075                HDF5OpenGroup /Z fileID , groupName, groupID
1076
1077                if(!groupID)
1078                // don't create the group it the name isn't right -- throw up an error
1079                        //HDF5CreateGroup /Z fileID, groupName, groupID
1080                        err = 1
1081                        HDF5CloseFile /Z fileID
1082                        DoAlert 0, "HDF5 group does not exist "+groupName+varname
1083                        return(err)
1084                else
1085                        // get attributes and save them
1086                        //HDF5ListAttributes /Z fileID, groupName    this is returning null. expect it to return semicolon delimited list of attributes
1087                        //Wave attributes = S_HDF5ListAttributes
1088                endif
1089       
1090                HDF5SaveData /O /Z /IGOR=0 wav, groupID, varName
1091                if (V_flag != 0)
1092                        err = 1
1093                        abort "Cannot save wave to HDF5 dataset " + varName
1094                endif   
1095               
1096               
1097                //attributes - something could be added here as optional parameters and flagged
1098//              String attributes = "units"
1099//              Make/O/T/N=1 tmp
1100//              tmp[0] = "dimensionless"
1101//              HDF5SaveData /O /Z /IGOR=0 /A=attributes tmp, groupID, varName
1102//              if (V_flag != 0)
1103//                      err = 1
1104//                      abort "Cannot save attributes to HDF5 dataset"
1105//              endif   
1106        catch
1107
1108        endtry
1109       
1110        if(groupID)
1111                HDF5CloseGroup /Z groupID
1112        endif
1113       
1114        if(fileID)
1115                HDF5CloseFile /Z fileID
1116        endif
1117
1118        setDataFolder $cDF
1119        return err
1120end
1121
1122//////////////////////////////
1123//////////////////////////////
1124//////////////////////////////
1125
1126
1127
1128
1129
1130
1131//////////
1132//
1133// These procedures are needed to write out MASK and DIV files
1134//
1135////////
1136
1137
1138//
1139// saves a specified folder, with a given filename.
1140// saves to the home path
1141//
1142Proc Save_VSANS_file(dfPath, filename)
1143        String dfPath   ="root:VSANS_file"              // e.g., "root:FolderA" or ":"
1144        String filename = "Test_VSANS_file.h5"
1145       
1146        H_NXSANS_SaveGroupAsHDF5(dfPath, filename)
1147End
1148
1149
1150//     
1151// this is my procedure to save the folders to HDF5, once I've filled the folder tree
1152//
1153// this does NOT save attributes, but gets the folder structure correct
1154//
1155Function H_NXSANS_SaveGroupAsHDF5(dfPath, filename)
1156        String dfPath   // e.g., "root:FolderA" or ":"
1157        String filename
1158
1159        Variable result = 0     // 0 means no error
1160       
1161        Variable fileID
1162        PathInfo home
1163        if(V_flag == 1)
1164                HDF5CreateFile/P=home /O /Z fileID as filename
1165        else
1166                HDF5CreateFile /O/I /Z fileID as filename
1167        endif
1168        if (V_flag != 0)
1169                Print "HDF5CreateFile failed"
1170                return -1
1171        endif
1172
1173        HDF5SaveGroup /IGOR=0 /O /R /Z $dfPath, fileID, "."
1174//      HDF5SaveGroup /O /R /Z $dfPath, fileID, "."
1175        if (V_flag != 0)
1176                Print "HDF5SaveGroup failed"
1177                result = -1
1178        endif
1179       
1180        HDF5CloseFile fileID
1181
1182        return result
1183End
1184
Note: See TracBrowser for help on using the repository browser.