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

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

re-wrote raw data reader for significant speed boost (mostly by skipping the read of DAS_logs)

added centroid calculation to the Marquee

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