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

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

more additions to the basic infrastructure for VSANS

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