; docformat = 'rst' ;+ ; :Categories: ; file i/o, hdf5, sdf ; ; :Requires: ; IDL 8.0 ; ; :Author: ; Michael Galloy ; ; :Copyright: ; This library is released under a BSD-type license. ; ; Copyright (c) 2007-2010, Michael Galloy ; ; All rights reserved. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions are ; met: ; ; a. Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; b. Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in ; the documentation and/or other materials provided with the ; distribution. ; c. Neither the name of Michael Galloy nor the names of its ; contributors may be used to endorse or promote products derived ; from this software without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS ; IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR ; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;- ;+ ; Dumps the contents of the file. ;- pro mgffhdf5file::dump compile_opt strictarr mg_h5_dump, self.filename end ;+ ; Start the HDF 5 browser on the file. ;- pro mgffhdf5file::browse compile_opt strictarr ok = h5_browser(self.filename) end ;+ ; Open an HDF 5 file. ; ; :Private: ; ; :Keywords: ; error : out, optional, type=long ; error code: 0 for none ;- pro mgffhdf5file::_open, error=error compile_opt strictarr catch, error if (error ne 0L) then begin catch, /cancel return endif self.id = h5f_open(self.filename) end ;+ ; Close an HDF 5 file. ; ; :Private: ; ; :Keywords: ; error : out, optional, type=long ; error code: 0 for none ;- pro mgffhdf5file::_close, error=error compile_opt strictarr catch, error if (error ne 0L) then begin catch, /cancel return endif h5f_close, self.id end ;+ ; Get object info for child object inside file. ; ; :Private: ; ; :Params: ; name : in, required, type=string ; name of child object ; ; :Keywords: ; error : out, optional, type=long ; error code: 0 for none ;- function mgffhdf5file::_statObject, name, error=error compile_opt strictarr catch, error if (error ne 0L) then begin catch, /cancel return, -1 endif for i = 0L, h5g_get_num_objs(self.id) - 1L do begin ; find first case-insensitive match objName = h5g_get_obj_name_by_idx(self.id, i) if (strcmp(objName, name, /fold_case)) then begin name = objName break endif endfor return, h5g_get_objinfo(self.id, name) end ;+ ; Output for `HELP` for file. ; ; :Returns: ; string ; ; :Params: ; varname : in, required, type=string ; name of variable containing group object ;- function mgffhdf5file::_overloadHelp, varname compile_opt strictarr type = obj_class(self) specs = string(self.filename, format='(%"<%s>")') return, string(varname, type, specs, format='(%"%-15s %-9s = %s")') end ;+ ; Output for `PRINT` for group. ; ; :Returns: ; string ;- function mgffhdf5file::_overloadPrint compile_opt strictarr nmembers = h5g_get_num_objs(self.id) names = strarr(nmembers) types = strarr(nmembers) for g = 0L, nmembers - 1L do begin names[g] = h5g_get_obj_name_by_idx(self.id, g) info = h5g_get_objinfo(self.id, names[g]) types[g] = info.type endfor listing = mg_strmerge(' ' + names + ' (' + strlowcase(types) + ')') return, string(self.filename, listing, format='(%"HDF5 file: %s\n%s")') end function mgffhdf5file::_overloadDotRightSide, name, isRange, ss1, ss2, ss3, $ ss4, ss5, ss6, ss7, ss8 compile_opt strictarr on_error, 2 objInfo = self->_statObject(name, error=error) if (error ne 0L) then message, string(name, format='(%"object %s not found")') ; TODO: search existing children before creating a new one case objInfo.type of 'GROUP': r = obj_new('MGffHDF5Group', parent_identifier=self.id, name=name) 'DATASET': r = obj_new('MGffHDF5Dataset', parent_identifier=self.id, name=name) 'TYPE': ; TODO: implement 'LINK': ; TODO: implement 'UNKNOWN': message, string(name, format='(%"object %s unknown")') else: begin ; TODO: check for attribute message, string(name, format='(%"object %s unknown")') end endcase self.children->add, r return, r end ;+ ; Handles accessing groups/variables, particularly those with case-sensitive ; names or spaces/other characters in their names. ; ; :Examples: ; For example:: ; ; h = mg_h5(file_which('hdf5_test.h5')) ; d = h['2D int array'] ;- function mgffhdf5file::_overloadBracketsRightSide, isRange, $ ss1, ss2, ss3, ss4, $ ss5, ss6, ss7, ss8 compile_opt strictarr on_error, 2 objInfo = self->_statObject(ss1, error=error) if (error ne 0L) then message, string(ss1, format='(%"object %s not found")') ; TODO: search existing children before creating a new one case objInfo.type of 'GROUP': result = obj_new('MGffHDF5Group', parent_identifier=self.id, name=ss1) 'DATASET': result = obj_new('MGffHDF5Dataset', parent_identifier=self.id, name=ss1) 'TYPE': ; TODO: implement 'LINK': ; TODO: implement 'UNKNOWN': message, string(ss1, format='(%"object %s unknown")') else: begin ; TODO: check for attribute message, string(ss1, format='(%"object %s unknown")') end endcase self.children->add, result if (n_elements(ss2) gt 0L) then begin return, result->_overloadBracketsRightSide(isRange[1:*], ss2, ss3, ss4, ss5, ss6, ss7, ss8) endif else begin return, result endelse end ;+ ; Free resources of the HDF 5 file, including its children. ;- pro mgffhdf5file::cleanup compile_opt strictarr obj_destroy, self.children self->_close end ;+ ; Creates HDF 5 object. ; ; :Returns: ; 1 for success, 0 for failure ;- function mgffhdf5file::init, filename=filename, _extra=e compile_opt strictarr on_error, 2 self.filename = n_elements(filename) eq 0L ? '' : filename self.children = obj_new('IDL_Container') self->_open, error=error if (error ne 0L) then message, 'invalid HDF5 file' return, 1 end ;+ ; Define instance variables and class inheritance. ; ; :Fields: ; filename ; name of HDF 5 file ; id ; HDF 5 object identifier for file ; children ; IDL_Container of children objects ;- pro mgffhdf5file__define compile_opt strictarr define = { MGffHDF5File, inherits IDL_Object, $ filename: '', $ id: 0L, $ children: obj_new() $ } end