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

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

updating the IgorVersion? pragma to v7.0 for all files to be consistent.

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