11module HDF5
22 class Dataset
3- H5P_DEFAULT = 0
4-
53 class << self
64 def create ( parent_id , name , data )
75 values = normalize_data ( data )
86 dims = ::FFI ::MemoryPointer . new ( :ulong_long , 1 )
97 dims . write_array_of_ulong_long ( [ values . length ] )
108 datatype_id = datatype_id_for ( values )
119 dataspace_id = HDF5 ::FFI . H5Screate_simple ( 1 , dims , nil )
12- raise "Failed to create dataspace for dataset: #{ name } " if dataspace_id < 0
10+ raise HDF5 :: Error , "Failed to create dataspace for dataset: #{ name } " if dataspace_id < 0
1311
14- dataset_id = HDF5 ::FFI . H5Dcreate2 ( parent_id , name , datatype_id , dataspace_id , H5P_DEFAULT , H5P_DEFAULT ,
15- H5P_DEFAULT )
16- dataset = from_id ( dataset_id , name )
12+ dataset = from_id (
13+ HDF5 ::FFI . H5Dcreate2 ( parent_id , name , datatype_id , dataspace_id , HDF5 ::DEFAULT_PROPERTY_LIST ,
14+ HDF5 ::DEFAULT_PROPERTY_LIST , HDF5 ::DEFAULT_PROPERTY_LIST ) , name
15+ )
1716 dataset . write ( values )
18- dataset
17+ return dataset unless block_given?
18+
19+ begin
20+ yield dataset
21+ ensure
22+ dataset . close
23+ end
1924 ensure
2025 HDF5 ::FFI . H5Sclose ( dataspace_id ) if dataspace_id && dataspace_id >= 0
2126 end
2227
2328 def open ( parent_id , name )
24- from_id ( HDF5 ::FFI . H5Dopen2 ( parent_id , name , H5P_DEFAULT ) , name )
29+ dataset = from_id ( HDF5 ::FFI . H5Dopen2 ( parent_id , name , HDF5 ::DEFAULT_PROPERTY_LIST ) , name )
30+ return dataset unless block_given?
31+
32+ begin
33+ yield dataset
34+ ensure
35+ dataset . close
36+ end
2537 end
2638
2739 def normalize_data ( data )
2840 values = data . is_a? ( Array ) ? data : [ data ]
29- raise 'Dataset data must not be empty' if values . empty?
30- raise 'Nested arrays are not supported' if values . any? { |value | value . is_a? ( Array ) }
41+ raise HDF5 :: Error , 'Dataset data must not be empty' if values . empty?
42+ raise HDF5 :: Error , 'Nested arrays are not supported' if values . any? { |value | value . is_a? ( Array ) }
3143
3244 values
3345 end
@@ -38,7 +50,7 @@ def datatype_id_for(data)
3850 elsif data . all? { |value | value . is_a? ( Numeric ) }
3951 HDF5 ::FFI . H5T_NATIVE_DOUBLE
4052 else
41- raise 'Only numeric dataset data is supported'
53+ raise HDF5 :: Error , 'Only numeric dataset data is supported'
4254 end
4355 end
4456
@@ -64,7 +76,7 @@ def from_id(dataset_id, name)
6476 end
6577
6678 def initialize ( parent_id , name )
67- initialize_from_id ( HDF5 ::FFI . H5Dopen2 ( parent_id , name , H5P_DEFAULT ) , name )
79+ initialize_from_id ( HDF5 ::FFI . H5Dopen2 ( parent_id , name , HDF5 :: DEFAULT_PROPERTY_LIST ) , name )
6880 end
6981
7082 def attrs
@@ -75,19 +87,23 @@ def write(data)
7587 values = self . class . normalize_data ( data )
7688 buffer = self . class . buffer_for ( values )
7789 mem_type_id = self . class . datatype_id_for ( values )
78- status = HDF5 ::FFI . H5Dwrite ( @dataset_id , mem_type_id , H5P_DEFAULT , H5P_DEFAULT , H5P_DEFAULT , buffer )
79- raise 'Failed to write dataset' if status < 0
90+ status = HDF5 ::FFI . H5Dwrite ( @dataset_id , mem_type_id , HDF5 ::DEFAULT_PROPERTY_LIST , HDF5 ::DEFAULT_PROPERTY_LIST ,
91+ HDF5 ::DEFAULT_PROPERTY_LIST , buffer )
92+ raise HDF5 ::Error , 'Failed to write dataset' if status < 0
8093
8194 data
8295 end
8396
8497 def close
98+ return if @dataset_id . nil?
99+
85100 HDF5 ::FFI . H5Dclose ( @dataset_id )
101+ @dataset_id = nil
86102 end
87103
88104 def dtype
89105 datatype_id = HDF5 ::FFI . H5Dget_type ( @dataset_id )
90- raise 'Failed to get datatype' if datatype_id < 0
106+ raise HDF5 :: Error , 'Failed to get datatype' if datatype_id < 0
91107
92108 HDF5 ::FFI . H5Tget_class ( datatype_id )
93109 ensure
@@ -96,10 +112,10 @@ def dtype
96112
97113 def shape
98114 dataspace_id = HDF5 ::FFI . H5Dget_space ( @dataset_id )
99- raise 'Failed to get dataspace' if dataspace_id < 0
115+ raise HDF5 :: Error , 'Failed to get dataspace' if dataspace_id < 0
100116
101117 ndims = HDF5 ::FFI . H5Sget_simple_extent_ndims ( dataspace_id )
102- raise 'Failed to get number of dimensions' if ndims < 0
118+ raise HDF5 :: Error , 'Failed to get number of dimensions' if ndims < 0
103119
104120 dims = ::FFI ::MemoryPointer . new ( :ulong_long , ndims )
105121 HDF5 ::FFI . H5Sget_simple_extent_dims ( dataspace_id , dims , nil )
@@ -110,35 +126,36 @@ def shape
110126 end
111127
112128 def read
113- dtype = dtype ( )
114- shape = shape ( )
129+ current_dtype = dtype
130+ current_shape = shape
115131
116- total_elements = shape . inject ( :* )
117- case dtype
132+ total_elements = current_shape . inject ( :* )
133+ case current_dtype
118134 when :H5T_INTEGER
119135 read_integer_data ( total_elements )
120136 when :H5T_FLOAT
121137 read_float_data ( total_elements )
122138 when :H5T_STRING
123139 read_string_data ( total_elements )
124140 else
125- raise 'Unsupported datatype'
141+ raise HDF5 :: Error , 'Unsupported datatype'
126142 end
127143 end
128144
129145 def read_integer_data ( total_elements )
130146 buffer = ::FFI ::MemoryPointer . new ( :int , total_elements )
131- status = HDF5 ::FFI . H5Dread ( @dataset_id , HDF5 ::FFI . H5T_NATIVE_INT , H5P_DEFAULT , H5P_DEFAULT , H5P_DEFAULT , buffer )
132- raise 'Failed to read integer dataset' if status < 0
147+ status = HDF5 ::FFI . H5Dread ( @dataset_id , HDF5 ::FFI . H5T_NATIVE_INT , HDF5 ::DEFAULT_PROPERTY_LIST ,
148+ HDF5 ::DEFAULT_PROPERTY_LIST , HDF5 ::DEFAULT_PROPERTY_LIST , buffer )
149+ raise HDF5 ::Error , 'Failed to read integer dataset' if status < 0
133150
134151 buffer . read_array_of_int ( total_elements )
135152 end
136153
137154 def read_float_data ( total_elements )
138155 buffer = ::FFI ::MemoryPointer . new ( :double , total_elements )
139- status = HDF5 ::FFI . H5Dread ( @dataset_id , HDF5 ::FFI . H5T_NATIVE_DOUBLE , H5P_DEFAULT , H5P_DEFAULT , H5P_DEFAULT ,
140- buffer )
141- raise 'Failed to read float dataset' if status < 0
156+ status = HDF5 ::FFI . H5Dread ( @dataset_id , HDF5 ::FFI . H5T_NATIVE_DOUBLE , HDF5 :: DEFAULT_PROPERTY_LIST ,
157+ HDF5 :: DEFAULT_PROPERTY_LIST , HDF5 :: DEFAULT_PROPERTY_LIST , buffer )
158+ raise HDF5 :: Error , 'Failed to read float dataset' if status < 0
142159
143160 buffer . read_array_of_double ( total_elements )
144161 end
@@ -150,7 +167,7 @@ def read_string_data(total_elements)
150167 private
151168
152169 def initialize_from_id ( dataset_id , name )
153- raise "Failed to open dataset: #{ name } " if dataset_id < 0
170+ raise HDF5 :: Error , "Failed to open dataset: #{ name } " if dataset_id < 0
154171
155172 @dataset_id = dataset_id
156173 @name = name
0 commit comments