source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/VSANS/V_ReadWrite_HDF5.ipf @ 960

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

more work with SANS and VSANS Nexus files, still trying to organize the r/w routines for just the basic testing of the first pass of NICE-generated files. Ditched the idea of generating the files from Igor, since DAS_log is not included. Now the plan is to start from a NICE/Nexus template. All still EXTREMELY fluid at this point.

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