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

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

more additions to the R/W functions to access VSANS data files

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