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

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

multiple changes to improve the functionality of VCALC

more values are reported, and the IQ plot now accounts for a beam stop shadowing the low q region. Qmin and qmax values are reported for each panel. the beam intensity value is more realistic, with correct SSD values.

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