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

Last change on this file since 1117 was 1117, checked in by srkline, 4 years ago

extensive changes to accomodate 1x1 binning of the HighRes? detector. It is implemented as a global flag. Currently only 4x4 and 1x1 are allowed. 1x1 has never been tested in reality, only simulated data - so my assumed dimensions may not be correct. look for TODOHIGHRES in the file for places that may need to be updated for different file dimensions. Testing of the simulated data is proving to be excruciatingly slow, but passable for a test. Speed optimization will be needed if this is the final solution. Memory management will also be an issue since every "copy" of the highRes matrix is enormous. Carry as few of these around as possible in the future to keep the experiment size to something reasonable.

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