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

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

New dimensions added for the back detector. many functions neede to be updated to accomodate these changes. Beam center is handled in the same way (in cm, not pixels) as other panels even though this panel is like the 2D detectors on SANS.

Still missing is the real values for caibration, pixel size, dead time, etc. that are yet to be measured.

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