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

Last change on this file since 977 was 977, checked in by srkline, 6 years ago

changes, mostly to Test_RAW_Panel, to add more controls and to add the hook function, which is much more complex now with a subWindow.

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