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

Last change on this file since 1058 was 1058, checked in by srkline, 5 years ago

changes to HDFLoadGroup to use the new R=2 flag to allow reading of duplicated groups in the data file (the temperature log). Requires Igor 7.05+ and HDF5XOP 1.24+

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