Class: HDF5::AttributeManager
- Inherits:
-
Object
- Object
- HDF5::AttributeManager
- Defined in:
- lib/hdf5/attribute.rb
Instance Method Summary collapse
- #[](attr_name) ⇒ Object
- #[]=(attr_name, value) ⇒ Object
- #create(attr_name, value) ⇒ Object
- #delete(attr_name) ⇒ Object
-
#initialize(dataset_id, context = nil) ⇒ AttributeManager
constructor
A new instance of AttributeManager.
- #key?(attr_name) ⇒ Boolean
- #keys ⇒ Object
- #modify(attr_name, value, casting: :safe) ⇒ Object
- #write(attr_name, value) ⇒ Object
Constructor Details
#initialize(dataset_id, context = nil) ⇒ AttributeManager
Returns a new instance of AttributeManager.
85 86 87 88 |
# File 'lib/hdf5/attribute.rb', line 85 def initialize(dataset_id, context = nil) @dataset_id = dataset_id @context = context end |
Instance Method Details
#[](attr_name) ⇒ Object
90 91 92 93 94 95 96 |
# File 'lib/hdf5/attribute.rb', line 90 def [](attr_name) @context&.ensure_open!(@dataset_id) attr = Attribute.new(@dataset_id, attr_name, @context) attr.read ensure attr.close if attr end |
#[]=(attr_name, value) ⇒ Object
98 99 100 |
# File 'lib/hdf5/attribute.rb', line 98 def []=(attr_name, value) write(attr_name, value) end |
#create(attr_name, value) ⇒ Object
133 134 135 136 137 |
# File 'lib/hdf5/attribute.rb', line 133 def create(attr_name, value) raise HDF5::Error, "Attribute already exists: #{attr_name}" if key?(attr_name) write(attr_name, value) end |
#delete(attr_name) ⇒ Object
125 126 127 128 129 130 131 |
# File 'lib/hdf5/attribute.rb', line 125 def delete(attr_name) @context&.ensure_open!(@dataset_id) status = HDF5::FFI.H5Adelete(@dataset_id, attr_name) raise HDF5::Error, "Failed to delete attribute: #{attr_name}" if status < 0 self end |
#key?(attr_name) ⇒ Boolean
117 118 119 120 121 122 123 |
# File 'lib/hdf5/attribute.rb', line 117 def key?(attr_name) @context&.ensure_open!(@dataset_id) exists = HDF5::FFI.H5Aexists(@dataset_id, attr_name) raise HDF5::Error, "Failed to check attribute existence: #{attr_name}" if exists.negative? exists.positive? end |
#keys ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/hdf5/attribute.rb', line 102 def keys @context&.ensure_open!(@dataset_id) names = [] index = ::FFI::MemoryPointer.new(:ulong_long) index.write_ulong_long(0) callback = ::FFI::Function.new(:int, i[int64_t string pointer pointer]) do |_, name, _, _| names << name 0 end status = HDF5::FFI.H5Aiterate2(@dataset_id, :H5_INDEX_NAME, :H5_ITER_NATIVE, index, callback, nil) raise HDF5::Error, 'Failed to iterate over attributes' if status < 0 names end |
#modify(attr_name, value, casting: :safe) ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/hdf5/attribute.rb', line 139 def modify(attr_name, value, casting: :safe) @context&.ensure_open!(@dataset_id) raise HDF5::Error, "Attribute not found: #{attr_name}" unless key?(attr_name) attr_id = HDF5::FFI.H5Aopen(@dataset_id, attr_name, HDF5::DEFAULT_PROPERTY_LIST) raise HDF5::Error, "Failed to open attribute: #{attr_name}" if attr_id < 0 type_id = HDF5::FFI.H5Aget_type(attr_id) space_id = HDF5::FFI.H5Aget_space(attr_id) raise HDF5::Error, "Failed to inspect attribute: #{attr_name}" if type_id < 0 || space_id < 0 if HDF5::FFI.H5Sget_simple_extent_type(space_id) == :H5S_NULL unless value.is_a?(HDF5::Empty) && value.dtype.to_sym == DType.for_hdf5(type_id).to_sym raise HDF5::ShapeError, 'Cannot assign a value to a Null attribute' end return value end if HDF5::FFI.H5Tget_class(type_id) == :H5T_STRING unless HDF5::StringCodec.variable?(type_id) raise UnsupportedTypeError, 'Fixed-length string attributes are not yet supported' end encoding = HDF5::StringCodec.encoding_for(type_id) string_values, string_shape = HDF5::StringCodec.normalize_data(value, encoding:) unless string_shape == attribute_shape(space_id) raise HDF5::ShapeError, 'Attribute shape must not change when modifying' end buffer, _string_pointers = HDF5::StringCodec.buffer_for_values(string_values, encoding:) status = HDF5::FFI.H5Awrite(attr_id, type_id, buffer) else dtype_object = DType.for_hdf5(type_id) values = HDF5::DataHelpers.normalize_data(value, label: 'Attribute data', dtype: dtype_object, casting:, convert: false) expected_shape = attribute_shape(space_id) raise HDF5::Error, 'Attribute shape must not change when modifying' unless values.shape == expected_shape status = HDF5::FFI.H5Awrite(attr_id, DType.for_numo(values).memory_type_id, HDF5::DataHelpers.buffer_for(values)) end raise HDF5::Error, "Failed to modify attribute: #{attr_name}" if status < 0 value ensure HDF5::FFI.H5Sclose(space_id) if space_id && space_id >= 0 HDF5::FFI.H5Tclose(type_id) if type_id && type_id >= 0 HDF5::FFI.H5Aclose(attr_id) if attr_id && attr_id >= 0 end |
#write(attr_name, value) ⇒ Object
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/hdf5/attribute.rb', line 187 def write(attr_name, value) @context&.ensure_open!(@dataset_id) empty_data = value.is_a?(HDF5::Empty) if empty_data && value.dtype.kind == :string raise UnsupportedFeatureError, 'Creating Null string attributes is not yet supported' end string_data = HDF5::StringCodec.string_data?(value) string_values, string_shape = HDF5::StringCodec.normalize_data(value) if string_data values = HDF5::DataHelpers.normalize_data(value, label: 'Attribute data') unless string_data || empty_data dtype_object = empty_data ? value.dtype : DType.for_numo(values) unless string_data type_id = string_data ? HDF5::StringCodec.datatype_id : dtype_object.storage_type_id exists = HDF5::FFI.H5Aexists(@dataset_id, attr_name) raise HDF5::Error, "Failed to check attribute existence: #{attr_name}" if exists.negative? if exists.positive? status = HDF5::FFI.H5Adelete(@dataset_id, attr_name) raise HDF5::Error, "Failed to replace attribute: #{attr_name}" if status < 0 end dataspace_id = create_dataspace(empty_data ? nil : (string_data ? string_shape : values.shape)) raise HDF5::Error, 'Failed to create attribute dataspace' if dataspace_id < 0 attr_id = HDF5::FFI.H5Acreate2( @dataset_id, attr_name, type_id, dataspace_id, HDF5::DEFAULT_PROPERTY_LIST, HDF5::DEFAULT_PROPERTY_LIST ) raise HDF5::Error, "Failed to create attribute: #{attr_name}" if attr_id < 0 return value if empty_data buffer, _string_pointers = if string_data HDF5::StringCodec.buffer_for_values(string_values) else [HDF5::DataHelpers.buffer_for(values), nil] end memory_type_id = string_data ? type_id : dtype_object.memory_type_id status = HDF5::FFI.H5Awrite(attr_id, memory_type_id, buffer) raise HDF5::Error, "Failed to write attribute: #{attr_name}" if status < 0 value ensure HDF5::FFI.H5Aclose(attr_id) if attr_id && attr_id >= 0 HDF5::FFI.H5Sclose(dataspace_id) if dataspace_id && dataspace_id >= 0 HDF5::FFI.H5Tclose(type_id) if string_data && type_id && type_id >= 0 end |