source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/VSANS/VC_HDF5_VSANS_Utils.ipf @ 955

Last change on this file since 955 was 955, checked in by srkline, 8 years ago

some reorganization of the r/w routines to generate HDF test files for SANS and VSANS (all are housed together for testing). also some reorganization of the detector binning routines to get functions grouped in more logical locations.

File size: 13.0 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2
3//
4// This file has lots of utility procedures to be able to read/write
5// test HDF5 files for SANS and VSANS in Nexus format
6//
7// It doesn't have the NICE logs, but has everything that I
8// can think of here.
9//
10
11//
12// There's an odd sequence of steps that need to be done to use HDFGateway
13// to most easily write out attributes, and be able to read then back in.
14// Rather awkward, but it works without me needing to go nuts with an atomistic
15// understanding of HDF5. This is necessary for me to be able to write out
16// Nexus files, which is important both for testing, and for simulation.
17//
18// This is done as a set of macros that need to be applied in a specific sequence
19// in order to be able to generate HDF5___xref
20// Ideally, the HDF5___xref wave can be saved/imported to make proper saving possible
21// once the "tree" is finalized.
22//
23//
24// The basic saving routines are here, just as Proc rather than Macro menu clutter
25//
26
27
28// Next... think of all of R/W access needed
29//
30// the simple read/write works...
31// linear_data does not seem to need to be transposed at all
32//
33//  -- this seems too easy. what am I doing wrong? Is something getting garbled when I
34// write back any single values back to the file
35//
36// -- try a string value next
37// -- then start to write the generic get/write functions
38//
39
40//
41// do I ditch the RealsRead/IntegersRead/TextRead? It makes little sense now.
42// maybe copy a "dataInfo" folder/subfolders. can't keep them all (bloat)
43// but then what about multiple files added together?
44//
45
46
47
48Macro Setup_VSANS_Struct()
49
50        // lays out the tree and fills with dummy values
51        H_Setup_VSANS_Structure()
52       
53        // writes in the attributes
54        H_Fill_VSANS_Attributes()
55       
56        // fill in with VCALC simulation bits
57        H_Fill_VSANS_wSim()
58       
59End
60
61Macro Save_VSANS_Nexus(fileName)
62        String fileName="Test_VSANS_file"
63
64        // save as HDF5 (no attributes saved yet)
65        Save_VSANS_file("root:VSANS_file", fileName+".h5")
66       
67        // read in a data file using the gateway-- reads from the home path
68        H_HDF5Gate_Read_Raw(fileName+".h5")
69       
70        // after reading in a "partial" file using the gateway (to generate the xref)
71        // Save the xref to disk (for later use)
72        Save_HDF5___xref("root:"+fileName,"HDF5___xref")
73       
74        // after you've generated the HDF5___xref, load it in and copy it
75        // to the necessary folder location.
76        Copy_HDF5___xref("root:VSANS_file", "HDF5___xref")
77       
78        // writes out the contents of a data folder using the gateway
79        H_HDF5Gate_Write_Raw("root:VSANS_file", fileName+".h5")
80
81        // re-load the data file using the gateway-- reads from the home path
82        // now with attributes
83        H_HDF5Gate_Read_Raw(fileName+".h5")
84       
85End
86
87
88
89Macro Setup_SANS_Struct()
90
91        // lays out the tree and fills with dummy values
92        H_Setup_SANS_Structure()
93       
94        // writes in the attributes
95        H_Fill_SANS_Attributes()
96       
97        // fill in with VCALC simulation bits
98        H_Fill_SANS_wSim()
99
100End
101
102Macro Save_SANS_Nexus(fileName)
103        String fileName="Test_SANS_file"
104       
105        // save as HDF5 (no attributes saved yet) (save_VSANS is actually generic HDF...)
106        Save_VSANS_file("root:SANS_file", fileName+".h5")
107       
108        // read in a data file using the gateway-- reads from the home path
109        H_HDF5Gate_Read_Raw(fileName+".h5")
110       
111        // after reading in a "partial" file using the gateway (to generate the xref)
112        // Save the xref to disk (for later use)
113        Save_HDF5___xref("root:"+fileName,"HDF5___xref")
114       
115        // after you've generated the HDF5___xref, load it in and copy it
116        // to the necessary folder location.
117        Copy_HDF5___xref("root:SANS_file", "HDF5___xref")
118       
119        // writes out the contents of a data folder using the gateway
120        H_HDF5Gate_Write_Raw("root:SANS_file", fileName+".h5")
121
122        // re-load the data file using the gateway-- reads from the home path
123        // now with attributes
124        H_HDF5Gate_Read_Raw(fileName+".h5")
125
126
127End
128
129
130
131
132
133//
134// saves a specified folder, with a given filename.
135// saves to the home path
136//
137Proc Save_VSANS_file(dfPath, filename)
138        String dfPath   ="root:VSANS_file"              // e.g., "root:FolderA" or ":"
139        String filename = "Test_VSANS_file.h5"
140       
141        H_NXSANS_SaveGroupAsHDF5(dfPath, filename)
142End
143
144
145//     
146// this is my procedure to save the folders to HDF5, once I've filled the folder tree
147//
148// this does NOT save attributes, but gets the fodler structure correct
149//
150Function H_NXSANS_SaveGroupAsHDF5(dfPath, filename)
151        String dfPath   // e.g., "root:FolderA" or ":"
152        String filename
153
154        Variable result = 0     // 0 means no error
155       
156        Variable fileID
157        HDF5CreateFile/P=home /O /Z fileID as filename
158        if (V_flag != 0)
159                Print "HDF5CreateFile failed"
160                return -1
161        endif
162
163        HDF5SaveGroup /IGOR=0 /O /R /Z $dfPath, fileID, "."
164//      HDF5SaveGroup /O /R /Z $dfPath, fileID, "."
165        if (V_flag != 0)
166                Print "HDF5SaveGroup failed"
167                result = -1
168        endif
169       
170        HDF5CloseFile fileID
171
172        return result
173End
174
175
176//
177// writes out the contents of a data folder using the gateway
178// -- the HDF5___xref wave must be present at the toep level for it to
179//    write out anything.
180//
181Proc H_HDF5Gate_Write_Raw(dfPath, filename)
182        String dfPath   ="root:VSANS_file"              // e.g., "root:FolderA" or ":"
183        String filename = "Test_VSANS_file.h5"
184       
185        // Check our work so far.
186        // If something prints, there was an error above.
187        print H5GW_ValidateFolder(dfPath)
188
189        print H5GW_WriteHDF5(dfPath, filename)
190       
191        SetDataFolder root:
192End
193
194//
195// read in a data file using the gateway
196//
197// reads from the home path
198//
199Proc H_HDF5Gate_Read_Raw(file)
200        String file
201//      NewDataFolder/O/S root:newdata
202        Print H5GW_ReadHDF5("", file)   // reads into current folder
203        SetDataFolder root:
204End
205
206
207//
208// after reading in a "partial" file using the gateway (to generate the xref)
209// Save the xref to disk (for later use)
210//
211Proc Save_HDF5___xref(dfPath, filename)
212        String dfPath   ="root:VSANS_file"              // e.g., "root:FolderA" or ":"
213        String filename = "HDF5___xref"
214
215        Save/T/P=home $(dfPath+":HDF5___xref") as "HDF5___xref.itx"
216
217//      Copy_HDF5___xref(dfPath, filename)
218       
219        SetDataFolder root:
220End
221
222//
223// after you've generated the HDF5___xref, load it in and copy it to
224// the necessary folder location.
225// - then all is set to *really* write out the file correctly, including the attributes
226//
227Proc Copy_HDF5___xref(dfPath, filename)
228        String dfPath   ="root:VSANS_file"              // e.g., "root:FolderA" or ":"
229        String filename = "HDF5___xref"
230
231        if(exists(filename) != 1)
232                //load it in   
233                LoadWave/T/P=home/O "HDF5___xref.itx"
234        endif
235       
236        Duplicate/O HDF5___xref, $(dfPath+":HDF5___xref")
237       
238        SetDataFolder root:
239End
240
241
242
243//////// testing procedures, may be of use, maybe not //////////////
244
245
246//////// Two procedures that test out Pete Jemain's HDF5Gateway
247//
248// This works fine, but it may not be terribly compatible with the way NICE will eventually
249// write out the data files. I'll have very little control over that and I'll need to cobble together
250// a bunch of fixes to cover up their mistakes.
251//
252// Using Nick Hauser's code as a starting point may be a lot more painful, but more flexible in the end.
253//
254// I'm completely baffled about what to do with attributes. Are they needed, is this the best way to deal
255// with them, do I care about reading them in, and if I do, why?
256//
257Proc H_HDF5Gate_WriteTest()
258
259        // create the folder structure
260        NewDataFolder/O/S root:mydata
261        NewDataFolder/O sasentry
262        NewDataFolder/O :sasentry:sasdata
263
264        // create the waves
265        Make/O :sasentry:sasdata:I0
266        Make/O :sasentry:sasdata:Q0
267
268        Make/O/N=0 Igor___folder_attributes
269        Make/O/N=0 :sasentry:Igor___folder_attributes
270        Make/O/N=0 :sasentry:sasdata:Igor___folder_attributes
271
272        // create the attributes
273        Note/K Igor___folder_attributes, "producer=IgorPro\rNX_class=NXroot"
274        Note/K :sasentry:Igor___folder_attributes, "NX_class=NXentry"
275        Note/K :sasentry:sasdata:Igor___folder_attributes, "NX_class=NXdata"
276        Note/K :sasentry:sasdata:I0, "units=1/cm\rsignal=1\rtitle=reduced intensity"
277        Note/K :sasentry:sasdata:Q0, "units=1/A\rtitle=|scattering vector|"
278
279        // create the cross-reference mapping
280        Make/O/T/N=(5,2) HDF5___xref
281        Edit/K=0 'HDF5___xref';DelayUpdate
282        HDF5___xref[0][1] = ":"
283        HDF5___xref[1][1] = ":sasentry"
284        HDF5___xref[2][1] = ":sasentry:sasdata"
285        HDF5___xref[3][1] = ":sasentry:sasdata:I0"
286        HDF5___xref[4][1] = ":sasentry:sasdata:Q0"
287        HDF5___xref[0][0] = "/"
288        HDF5___xref[1][0] = "/sasentry"
289        HDF5___xref[2][0] = "/sasentry/sasdata"
290        HDF5___xref[3][0] = "/sasentry/sasdata/I"
291        HDF5___xref[4][0] = "/sasentry/sasdata/Q"
292
293        // Check our work so far.
294        // If something prints, there was an error above.
295        print H5GW_ValidateFolder("root:mydata")
296
297        // set I0 and Q0 to your data
298
299        print H5GW_WriteHDF5("root:mydata", "mydata.h5")
300       
301        SetDataFolder root:
302End
303
304
305//
306// given a filename of a SANS data filename of the form
307// name.anything
308// returns the name as a string without the ".fbdfasga" extension
309//
310// returns the input string if a "." can't be found (maybe it wasn't there)
311//
312Function/S H_RemoveDotExtension(item)
313        String item
314        String invalid = item   //
315        Variable num=-1
316       
317        //find the "dot"
318        String runStr=""
319        Variable pos = strsearch(item,".",0)
320        if(pos == -1)
321                //"dot" not found
322                return (invalid)
323        else
324                //found, get all of the characters preceeding it
325                runStr = item[0,pos-1]
326                return (runStr)
327        Endif
328End
329
330
331//
332// Writing attributes to a group and to a dataset.
333// example from the WM documentation for HDF5SaveData
334//
335Function DemoAttributes(w)
336        Wave w
337
338        Variable result = 0     // 0 means no error
339       
340        // Create file
341        Variable fileID
342        HDF5CreateFile/P=home /O /Z fileID as "Test.h5"
343        if (V_flag != 0)
344                Print "HDF5CreateFile failed"
345                return -1
346        endif
347
348        // Write an attribute to the root group
349        Make /FREE /T /N=1 groupAttribute = "This is a group attribute"
350        HDF5SaveData /A="GroupAttribute" groupAttribute, fileID, "/"
351       
352        // Save wave as dataset
353        HDF5SaveData /O /Z w, fileID    // Uses wave name as dataset name
354        if (V_flag != 0)
355                Print "HDF5SaveData failed"
356                result = -1
357        endif
358
359        // Write an attribute to the dataset
360        Make /FREE /T /N=1 datasetAttribute = "This is a dataset attribute"
361        String datasetName = NameOfWave(w)
362        HDF5SaveData /A="DatasetAttribute" datasetAttribute, fileID, datasetName
363
364        HDF5CloseFile fileID
365       
366        return result
367End     // The attribute waves are automatically killed since they are free waves
368
369
370
371//     
372//Function H_Test_HDFWriteTrans(fname,val)
373//      String fname
374//      Variable val
375//     
376//     
377//      String str
378//      PathInfo home
379//      str = S_path
380//     
381//      H_WriteTransmissionToHeader(str+fname,val)
382//     
383//      return(0)
384//End
385//
386//Function H_WriteTransmissionToHeader(fname,trans)
387//      String fname
388//      Variable trans
389//     
390//      Make/O/D/N=1 wTmpWrite
391//      String groupName = "/Sample"    //      /Run1/Sample becomes groupName /Run1/Run1/Sample
392//      String varName = "TRNS"
393//      wTmpWrite[0] = trans //
394//
395//      variable err
396//      err = HDFWrite_Wave(fname, groupName, varName, wTmpWrite)
397//      KillWaves wTmpWrite
398//     
399//      //err not handled here
400//             
401//      return(0)
402//End
403
404
405
406Function H_Test_ListAttributes(fname,groupName)
407        String fname,groupName
408        Variable trans
409       
410//      Make/O/D/N=1 wTmpWrite
411//      String groupName = "/Sample"    //      /Run1/Sample becomes groupName /Run1/Run1/Sample
412//      String varName = "TRNS"
413//      wTmpWrite[0] = trans //
414        String str
415        PathInfo home
416        str = S_path
417       
418        variable err
419        err = H_HDF_ListAttributes(str+fname, groupName)
420       
421        //err not handled here
422               
423        return(0)
424End
425
426Function H_HDF_ListAttributes(fname, groupName)
427        String fname, groupName
428       
429        variable err=0, fileID,groupID
430        String cDF = getDataFolder(1), temp
431        String NXentry_name, attrValue=""
432       
433        STRUCT HDF5DataInfo di  // Defined in HDF5 Browser.ipf.
434        InitHDF5DataInfo(di)    // Initialize structure.
435       
436        try     
437                HDF5OpenFile /Z fileID  as fname  //open file read-write
438                if(!fileID)
439                        err = 1
440                        abort "HDF5 file does not exist"
441                endif
442               
443                HDF5OpenGroup /Z fileID , groupName, groupID
444
445        //      (QUOKKA) !! At the moment, there is no entry for sample thickness in our data file
446        //      therefore create new HDF5 group to enable write / patch command
447        //      comment out the following group creation once thickness appears in revised file
448       
449                if(!groupID)
450                        HDF5CreateGroup /Z fileID, groupName, groupID
451                        //err = 1
452                        //abort "HDF5 group does not exist"
453                else
454
455//                      HDF5AttributeInfo(fileID, "/", 1, "file_name", 0, di)
456                        HDF5AttributeInfo(fileID, "/", 1, "NeXus_version", 0, di)
457                        Print di
458
459//                      see the HDF5 Browser  for how to get the actual <value> of the attribute. See GetPreviewString in
460//        or in FillGroupAttributesList or in FillDatasetAttributesList (from FillLists)
461//                      it seems to be ridiculously complex to get such a simple bit of information - the HDF5BrowserData STRUCT
462//                      needs to be filled first. Ugh.
463                        attrValue = GetPreviewString(fileID, 1, di, "/entry", "cucumber")
464                        Print "attrValue = ",attrValue
465                       
466                       
467                        //get attributes and save them
468                        HDF5ListAttributes/TYPE=1 /Z fileID, groupName          //TYPE=1 means that we're referencing a group, not a dataset
469                        Print "S_HDF5ListAttributes = ", S_HDF5ListAttributes
470                       
471                        // passing the groupID works too, then the group name is not needed                     
472                        HDF5ListAttributes/TYPE=1 /Z groupID, "."               //TYPE=1 means that we're referencing a group, not a dataset
473                        Print "S_HDF5ListAttributes = ", S_HDF5ListAttributes
474                endif
475        catch
476
477                // catch any aborts here
478               
479        endtry
480       
481        if(groupID)
482                HDF5CloseGroup /Z groupID
483        endif
484       
485        if(fileID)
486                HDF5CloseFile /Z fileID
487        endif
488
489        setDataFolder $cDF
490        return err
491end
492
493
494/////////////// end of the testing procedures ////////////////
Note: See TracBrowser for help on using the repository browser.