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

Last change on this file since 970 was 970, checked in by srkline, 7 years ago

more additions and corrections to the V_get and V_write functions

creating a folder (not root) for the raw data files to be loaded

File size: 12.8 KB
Line 
1#pragma rtGlobals=3             // Use modern global access method and strict wave access.
2
3//
4// The base functions for R/W from HDF5 files.
5// All of the specific "get" and "write" functions call these base functions which are responsible
6// for all of the open/close mechanics.
7//
8// These VSANS file-specific functions are in:
9// V_HDF5_Read.ipf
10//               and
11// V_HDF5_Write.ipf
12//
13
14// data is read into:
15//      NewDataFolder/O/S root:Packages:NIST:VSANS:RawVSANS
16// so that the data folders of the raw data won't be lying around on the top level, looking like
17// 1D data sets and interfering.
18
19
20// the base data folder path where the raw data is loaded
21Strconstant ksBaseDFPath = "root:Packages:NIST:VSANS:RawVSANS:"
22
23
24
25// passing null file string presents a dialog
26Macro Read_HDF5_Raw_No_Attributes()
27        V_LoadHDF5Data("")
28End
29
30// TODO -- move the initializtion of the raw data folder to be in the as-yet unwritten initialization routine for
31// reduction. be sure that it's duplicated in the VCALC initialization too.
32//
33Proc V_LoadHDF5Data(file)
34        String file
35
36        NewDataFolder/O/S root:Packages:NIST:VSANS:RawVSANS
37//      SetDataFolder root:
38        Variable err= V_LoadHDF5_NoAtt(file)    // reads into current folder
39        SetDataFolder root:
40End
41
42
43// This loads for speed, since loading the attributes takes a LOT of time.
44//
45// this will load in the whole HDF file all at once.
46// Attributes are NOT loaded at all.
47//
48// TODO: remove the P=home restriction top make this more generic
49// -- get rid of bits leftover here that I don't need
50// -- be sure I'm using all of the correct flags in the HDF5LoadGroup operation
51//
52Function V_LoadHDF5_NoAtt(fileName, [hdf5Path])
53        String fileName, hdf5Path
54        if ( ParamIsDefault(hdf5Path) )
55                hdf5Path = "/"
56        endif
57
58        String status = ""
59
60        Variable fileID = 0
61        HDF5OpenFile/R/P=home/Z fileID as fileName              //read file from home directory?
62//      HDF5OpenFile/R/P=catPathName/Z fileID as fileName
63        if (V_Flag != 0)
64                return 0
65        endif
66
67        String/G root:file_path = S_path
68        String/G root:file_name = S_FileName
69       
70        if ( fileID == 0 )
71                Print fileName + ": could not open as HDF5 file"
72                return (0)
73        endif
74       
75//s_tic()               //fast
76       
77        SVAR tmpStr=root:file_name
78        fileName=tmpStr         //SRK - in case the file was chosen from a dialog
79       
80        //   read the data (too bad that HDF5LoadGroup does not read the attributes)
81        String base_name = StringFromList(0,FileName,".")
82        HDF5LoadGroup/Z/L=7/O/R/T=$base_name  :, fileID, hdf5Path               //      recursive
83        if ( V_Flag != 0 )
84                Print fileName + ": could not open as HDF5 file"
85                setdatafolder root:
86                return (0)
87        endif
88
89        HDF5CloseFile fileID
90       
91//s_toc()
92        return(0)
93end     
94
95
96// read a single real value
97// - fname passed in is the full path to the file on disk
98// - path is the path to the value in the HDF tree
99//
100// check to see if the value exists (It will be a wave)
101// -- if it does, return the value from the local folder
102// -- if not, read the file in, then return the value
103//
104Function V_getRealValueFromHDF5(fname,path)
105        String fname,path
106
107        String folderStr=""
108        Variable valExists=0
109       
110        folderStr = V_RemoveDotExtension(V_GetFileNameFromPathNoSemi(fname))
111       
112        if(Exists(ksBaseDFPath+folderStr+":"+path))
113                valExists=1
114        endif
115       
116        if(!valExists)
117                //then read in the file
118                V_LoadHDF5_NoAtt(fname)
119        endif
120
121// this should exist now - if not, I need to see the error
122        Wave/Z w = $(ksBaseDFPath+folderStr+":"+path)
123       
124        if(WaveExists(w))
125                return(w[0])
126        else
127                return(-999999)
128        endif   
129End
130
131// Returns a wave reference, not just a single value
132// ---then you pick what you need from the wave
133//
134// - fname passed in is the full path to the file on disk
135// - path is the path to the value in the HDF tree
136//
137// check to see if the value exists (It will be a wave)
138// -- if it does, return the value from the local folder
139// -- if not, read the file in, then return the value
140//
141Function/WAVE V_getRealWaveFromHDF5(fname,path)
142        String fname,path
143
144        String folderStr=""
145        Variable valExists=0
146       
147        folderStr = V_RemoveDotExtension(V_GetFileNameFromPathNoSemi(fname))
148       
149        if(Exists(ksBaseDFPath+folderStr+":"+path))
150                valExists=1
151        endif
152       
153        if(!valExists)
154                //then read in the file
155                V_LoadHDF5_NoAtt(fname)
156        endif
157
158// this should exist now - if not, I need to see the error
159        Wave wOut = $(ksBaseDFPath+folderStr+":"+path)
160       
161        return wOut
162       
163End
164
165// Returns a wave reference, not just a single value
166// ---then you pick what you need from the wave
167//
168// - fname passed in is the full path to the file on disk
169// - path is the path to the value in the HDF tree
170//
171// check to see if the value exists (It will be a wave)
172// -- if it does, return the value from the local folder
173// -- if not, read the file in, then return the value
174//
175Function/WAVE V_getTextWaveFromHDF5(fname,path)
176        String fname,path
177
178        String folderStr=""
179        Variable valExists=0
180       
181        folderStr = V_RemoveDotExtension(V_GetFileNameFromPathNoSemi(fname))
182       
183        if(Exists(ksBaseDFPath+folderStr+":"+path))
184                valExists=1
185        endif
186       
187        if(!valExists)
188                //then read in the file
189                V_LoadHDF5_NoAtt(fname)
190        endif
191
192// this should exist now - if not, I need to see the error
193        Wave/T wOut = $(ksBaseDFPath+folderStr+":"+path)
194       
195        return wOut
196       
197End
198
199
200//
201//   TODO
202// depricated? in HDF5 - store all of the values as real?
203// Igor sees no difference in real and integer variables (waves are different)
204// BUT-- Igor 7 will have integer variables
205//
206// truncate to integer before returning??
207//
208//  TODO
209// write a "getIntegerWave" function??
210//
211//////  integer values
212// reads 32 bit integer
213Function V_getIntegerFromHDF5(fname,path)
214        String fname                            //full path+name
215        String path                             //path to the hdf5 location
216       
217        Variable val = V_getRealValueFromHDF5(fname,path)
218       
219        val = round(val)
220        return(val)
221End
222
223
224// read a single string
225// - fname passed in is the full path to the file on disk
226// - path is the path to the value in the HDF tree
227// - num is the number of characters in the VAX string
228// check to see if the value exists (It will be a wave)
229// -- if it does, return the value from the local folder
230// -- if not, read the file in, then return the value
231//
232// TODO -- string could be checked for length, but returned right or wrong
233//
234Function/S V_getStringFromHDF5(fname,path,num)
235        String fname,path
236        Variable num
237
238        String folderStr=""
239        Variable valExists=0
240       
241        folderStr = V_RemoveDotExtension(V_GetFileNameFromPathNoSemi(fname))
242       
243        if(Exists(ksBaseDFPath+folderStr+":"+path))
244                valExists=1
245        endif
246       
247        if(!valExists)
248                //then read in the file
249                V_LoadHDF5_NoAtt(fname)
250        endif
251
252// this should exist now - if not, I need to see the error
253        Wave/T/Z tw = $(ksBaseDFPath+folderStr+":"+path)
254       
255        if(WaveExists(tw))
256       
257        //      if(strlen(tw[0]) != num)
258        //              Print "string is not the specified length"
259        //      endif
260               
261                return(tw[0])
262        else
263                return("The specified wave does not exist: " + path)
264        endif
265End
266
267
268
269///////////////////////////////
270
271//
272//Write Wave 'wav' to hdf5 file 'fname'
273//Based on code from ANSTO (N. Hauser. nha 8/1/09)
274//
275// TODO:
276// -- figure out if this will write in the native format of the
277//     wave as passed in, or if it will only write as DP.
278// -- do I need to write separate functions for real, integer, etc.?
279//     
280// -- change the /P=home to the user-defined data path (which may be home)             
281//
282Function V_WriteWaveToHDF(fname, groupName, varName, wav)
283        String fname, groupName, varName
284        Wave wav
285       
286        variable err=0, fileID,groupID
287        String cDF = getDataFolder(1), temp
288        String NXentry_name
289       
290        try     
291                HDF5OpenFile/P=home /Z fileID  as fname  //open file read-write
292                if(!fileID)
293                        err = 1
294                        abort "HDF5 file does not exist"
295                endif
296               
297                //get the NXentry node name
298                HDF5ListGroup /TYPE=1 fileID, "/"
299                //remove trailing ; from S_HDF5ListGroup
300               
301                Print "S_HDF5ListGroup = ",S_HDF5ListGroup
302               
303                NXentry_name = S_HDF5ListGroup
304                NXentry_name = ReplaceString(";",NXentry_name,"")
305                if(strsearch(NXentry_name,":",0)!=-1) //more than one entry under the root node
306                        err = 1
307                        abort "More than one entry under the root node. Ambiguous"
308                endif
309                //concatenate NXentry node name and groupName   
310                // SRK - NOV2015 - dropped this and require the full group name passed in
311//              groupName = "/" + NXentry_name + groupName
312                Print "groupName = ",groupName
313                HDF5OpenGroup /Z fileID , groupName, groupID
314
315                if(!groupID)
316                        HDF5CreateGroup /Z fileID, groupName, groupID
317                        //err = 1
318                        //abort "HDF5 group does not exist"
319                else
320                        // get attributes and save them
321                        //HDF5ListAttributes /Z fileID, groupName    this is returning null. expect it to return semicolon delimited list of attributes
322                        //Wave attributes = S_HDF5ListAttributes
323                endif
324       
325                HDF5SaveData /O /Z /IGOR=0 wav, groupID, varName
326                if (V_flag != 0)
327                        err = 1
328                        abort "Cannot save wave to HDF5 dataset " + varName
329                endif   
330               
331               
332                //attributes - something could be added here as optional parameters and flagged
333//              String attributes = "units"
334//              Make/O/T/N=1 tmp
335//              tmp[0] = "dimensionless"
336//              HDF5SaveData /O /Z /IGOR=0 /A=attributes tmp, groupID, varName
337//              if (V_flag != 0)
338//                      err = 1
339//                      abort "Cannot save attributes to HDF5 dataset"
340//              endif   
341        catch
342
343        endtry
344
345// it is not necessary to close the group here. HDF5CloseFile will close the group as well     
346        if(groupID)
347                HDF5CloseGroup /Z groupID
348        endif
349       
350        if(fileID)
351                HDF5CloseFile /Z fileID
352        endif
353
354        setDataFolder $cDF
355        return err
356end
357
358//Write Wave 'wav' to hdf5 file 'fname'
359//Based on code from ANSTO (N. Hauser. nha 8/1/09)
360//
361// TODO
362//
363// -- change the /P=home to the user-defined data path (which may be home)             
364//
365Function V_WriteTextWaveToHDF(fname, groupName, varName, wav)
366        String fname, groupName, varName
367        Wave/T wav
368       
369        variable err=0, fileID,groupID
370        String cDF = getDataFolder(1), temp
371        String NXentry_name
372       
373        try     
374                HDF5OpenFile/P=home /Z fileID  as fname  //open file read-write
375                if(!fileID)
376                        err = 1
377                        abort "HDF5 file does not exist"
378                endif
379               
380                //get the NXentry node name
381                HDF5ListGroup /TYPE=1 fileID, "/"
382                //remove trailing ; from S_HDF5ListGroup
383               
384                Print "S_HDF5ListGroup = ",S_HDF5ListGroup
385               
386                NXentry_name = S_HDF5ListGroup
387                NXentry_name = ReplaceString(";",NXentry_name,"")
388                if(strsearch(NXentry_name,":",0)!=-1) //more than one entry under the root node
389                        err = 1
390                        abort "More than one entry under the root node. Ambiguous"
391                endif
392
393                //concatenate NXentry node name and groupName
394                // SRK - NOV2015 - dropped this and require the full group name passed in
395//              groupName = "/" + NXentry_name + groupName
396                Print "groupName = ",groupName
397
398                HDF5OpenGroup /Z fileID , groupName, groupID
399
400                if(!groupID)
401                        HDF5CreateGroup /Z fileID, groupName, groupID
402                        //err = 1
403                        //abort "HDF5 group does not exist"
404                else
405                        // get attributes and save them
406                        //HDF5ListAttributes /Z fileID, groupName    this is returning null. expect it to return semicolon delimited list of attributes
407                        //Wave attributes = S_HDF5ListAttributes
408                endif
409       
410                HDF5SaveData /O /Z /IGOR=0 wav, groupID, varName
411                if (V_flag != 0)
412                        err = 1
413                        abort "Cannot save wave to HDF5 dataset " + varName
414                endif   
415               
416               
417                //attributes - something could be added here as optional parameters and flagged
418//              String attributes = "units"
419//              Make/O/T/N=1 tmp
420//              tmp[0] = "dimensionless"
421//              HDF5SaveData /O /Z /IGOR=0 /A=attributes tmp, groupID, varName
422//              if (V_flag != 0)
423//                      err = 1
424//                      abort "Cannot save attributes to HDF5 dataset"
425//              endif   
426        catch
427
428        endtry
429       
430        if(groupID)
431                HDF5CloseGroup /Z groupID
432        endif
433       
434        if(fileID)
435                HDF5CloseFile /Z fileID
436        endif
437
438        setDataFolder $cDF
439        return err
440end
441
442//////////////////////////////
443//////////////////////////////
444//////////////////////////////
445
446Function V_KillNamedDataFolder(fname)
447        String fname
448       
449        Variable err=0
450       
451        String folderStr = V_GetFileNameFromPathNoSemi(fname)
452        folderStr = V_RemoveDotExtension(folderStr)
453       
454        KillDataFolder/Z $(ksBaseDFPath+folderStr)
455        err = V_flag
456       
457        return(err)
458end
459
460//given a filename of a SANS data filename of the form
461// name.anything
462//returns the name as a string without the ".fbdfasga" extension
463//
464// returns the input string if a"." can't be found (maybe it wasn't there"
465Function/S V_RemoveDotExtension(item)
466        String item
467        String invalid = item   //
468        Variable num=-1
469       
470        //find the "dot"
471        String runStr=""
472        Variable pos = strsearch(item,".",0)
473        if(pos == -1)
474                //"dot" not found
475                return (invalid)
476        else
477                //found, get all of the characters preceeding it
478                runStr = item[0,pos-1]
479                return (runStr)
480        Endif
481End
482
483//returns a string containing filename (WITHOUT the ;vers)
484//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
485//with the folders separated by colons
486//
487// called by MaskUtils.ipf, ProtocolAsPanel.ipf, WriteQIS.ipf
488//
489Function/S V_GetFileNameFromPathNoSemi(fullPath)
490        String fullPath
491       
492        Variable offset1,offset2
493        String filename=""
494        //String PartialPath
495        offset1 = 0
496        do
497                offset2 = StrSearch(fullPath, ":", offset1)
498                if (offset2 == -1)                              // no more colons ?
499                        fileName = FullPath[offset1,strlen(FullPath) ]
500                        //PartialPath = FullPath[0, offset1-1]
501                        break
502                endif
503                offset1 = offset2+1
504        while (1)
505       
506        //remove version number from name, if it's there - format should be: filename;N
507        filename =  StringFromList(0,filename,";")              //returns null if error
508       
509        Return filename
510End
Note: See TracBrowser for help on using the repository browser.