Skip to content

Commit 2f4ead2

Browse files
committed
WIP: add from options function and class methods
1 parent bf9bf6b commit 2f4ead2

File tree

3 files changed

+168
-1
lines changed

3 files changed

+168
-1
lines changed

src/hdf5plugin/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,13 @@
5252
Zfp,
5353
Zstd,
5454
)
55-
from ._utils import PLUGIN_PATH, get_config, get_filters, register # noqa
55+
from ._utils import ( # noqa
56+
PLUGIN_PATH,
57+
filter_from_options,
58+
get_config,
59+
get_filters,
60+
register,
61+
)
5662
from ._version import version # noqa
5763

5864
# Backward compatibility

src/hdf5plugin/_filters.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ class FilterBase(h5py.filters.FilterRefBase):
7474
filter_id: int
7575
filter_name: str
7676

77+
@classmethod
78+
def from_options(cls, filter_options: tuple[int, ...]) -> FilterBase:
79+
"""Returns compression arguments from HDF5 compression filters options
80+
81+
:raises ValueError: Unsupported filter_options
82+
"""
83+
raise NotImplementedError()
84+
7785

7886
class Bitshuffle(FilterBase):
7987
"""``h5py.Group.create_dataset``'s compression arguments for using bitshuffle filter.
@@ -148,6 +156,44 @@ def __init__(
148156
else:
149157
self.filter_options = (nelems, self.__COMPRESSIONS[cname])
150158

159+
@classmethod
160+
def from_options(cls, filter_options: tuple[int, ...]) -> Bitshuffle:
161+
"""Returns compression arguments from HDF5 compression filters options
162+
163+
:param filter_options: Expected format:
164+
165+
- Zstd: (_, _, _, nelems, compression_id=3, compression_level)
166+
- Other: (_, _, _, nelems, compression_id)
167+
168+
:raises ValueError: Unsupported filter_options
169+
"""
170+
if len(filter_options) not in (5, 6):
171+
raise ValueError(
172+
f"Expected 5 or 6 values in filter_options, got {len(filter_options)}"
173+
)
174+
175+
nelems = filter_options[3]
176+
177+
compression_id = filter_options[4]
178+
for cname, cid in cls.__COMPRESSIONS.items():
179+
if compression_id == cid:
180+
break
181+
else:
182+
raise ValueError(f"Unsupported compression id: {compression_id}")
183+
184+
if cname == "zstd":
185+
if len(filter_options) != 6:
186+
raise ValueError(
187+
f"Expected 6 values in filter_options, got {len(filter_options)}"
188+
)
189+
return cls(nelems, cname, clevel=filter_options[5])
190+
else:
191+
if len(filter_options) != 5:
192+
raise ValueError(
193+
f"Expected 5 values in filter_options, got {len(filter_options)}"
194+
)
195+
return cls(nelems, cname)
196+
151197

152198
class Blosc(FilterBase):
153199
"""``h5py.Group.create_dataset``'s compression arguments for using blosc filter.
@@ -204,6 +250,31 @@ def __init__(self, cname: str = "lz4", clevel: int = 5, shuffle: int = SHUFFLE):
204250
raise ValueError(f"shuffle={shuffle} is not supported")
205251
self.filter_options = (0, 0, 0, 0, clevel, shuffle, compression)
206252

253+
@classmethod
254+
def from_options(cls, filter_options: tuple[int, ...]) -> Blosc:
255+
"""Returns compression arguments from HDF5 compression filters options
256+
257+
:param filter_options: Expected format: (_, _, _, _, clevel, shuffle, compression)
258+
:raises ValueError: Unsupported filter_options
259+
"""
260+
if len(filter_options) != 7:
261+
raise ValueError(
262+
f"Expected 7 values in filter_options, got {len(filter_options)}"
263+
)
264+
265+
compression_id = filter_options[6]
266+
for cname, cid in cls.__COMPRESSIONS.items():
267+
if compression_id == cid:
268+
break
269+
else:
270+
raise ValueError(f"Unsupported compression id: {compression_id}")
271+
272+
return cls(
273+
cname,
274+
clevel=filter_options[4],
275+
shuffle=filter_options[5],
276+
)
277+
207278

208279
class Blosc2(FilterBase):
209280
"""``h5py.Group.create_dataset``'s compression arguments for using blosc2 filter.
@@ -272,6 +343,31 @@ def __init__(self, cname: str = "blosclz", clevel: int = 5, filters: int = SHUFF
272343
raise ValueError(f"filters={filters} is not supported")
273344
self.filter_options = (0, 0, 0, 0, clevel, filters, compression)
274345

346+
@classmethod
347+
def from_options(cls, filter_options: tuple[int, ...]) -> Blosc2:
348+
"""Returns compression arguments from HDF5 compression filters options
349+
350+
:param filter_options: Expected format: (_, _, _, _, clevel, filters, compression)
351+
:raises ValueError: Unsupported filter_options
352+
"""
353+
if len(filter_options) != 7:
354+
raise ValueError(
355+
f"Expected 7 values in filter_options, got {len(filter_options)}"
356+
)
357+
358+
compression_id = filter_options[6]
359+
for cname, cid in cls.__COMPRESSIONS.items():
360+
if compression_id == cid:
361+
break
362+
else:
363+
raise ValueError(f"Unsupported compression id: {compression_id}")
364+
365+
return cls(
366+
cname,
367+
clevel=filter_options[4],
368+
filters=filter_options[5],
369+
)
370+
275371

276372
class BZip2(FilterBase):
277373
"""``h5py.Group.create_dataset``'s compression arguments for using BZip2 filter.
@@ -297,6 +393,19 @@ def __init__(self, blocksize: int = 9):
297393
raise ValueError("blocksize must be in the range [1, 9]")
298394
self.filter_options = (blocksize,)
299395

396+
@classmethod
397+
def from_options(cls, filter_options: tuple[int, ...]) -> BZip2:
398+
"""Returns compression arguments from HDF5 compression filters options
399+
400+
:param filter_options: Expected format: (blocksize,)
401+
:raises ValueError: Unsupported filter_options
402+
"""
403+
if len(filter_options) != 1:
404+
raise ValueError(
405+
f"Expected 1 value in filter_options, got {len(filter_options)}"
406+
)
407+
return cls(blocksize=filter_options[0])
408+
300409

301410
class FciDecomp(FilterBase):
302411
"""``h5py.Group.create_dataset``'s compression arguments for using FciDecomp filter.
@@ -322,6 +431,18 @@ def __init__(self) -> None:
322431
"You may need to reinstall hdf5plugin with a recent version of pip, or rebuild it with a newer compiler."
323432
)
324433

434+
@classmethod
435+
def from_options(cls, filter_options: tuple[int, ...]) -> FciDecomp:
436+
"""Returns compression arguments from HDF5 compression filters options
437+
438+
:raises ValueError: Unsupported filter_options
439+
"""
440+
if len(filter_options) != 0:
441+
raise ValueError(
442+
f"Expected empty filter_options, got {len(filter_options)} values"
443+
)
444+
return cls()
445+
325446

326447
class LZ4(FilterBase):
327448
"""``h5py.Group.create_dataset``'s compression arguments for using lz4 filter.
@@ -348,6 +469,19 @@ def __init__(self, nbytes: int = 0):
348469
raise ValueError("clevel must be in the range [0, 2113929216]")
349470
self.filter_options = (nbytes,)
350471

472+
@classmethod
473+
def from_options(cls, filter_options: tuple[int, ...]) -> LZ4:
474+
"""Returns compression arguments from HDF5 compression filters options
475+
476+
:param filter_options: Expected format: (nbytes,)
477+
:raises ValueError: Unsupported filter_options
478+
"""
479+
if len(filter_options) != 1:
480+
raise ValueError(
481+
f"Expected 1 value in filter_options, got {len(filter_options)}"
482+
)
483+
return cls(nbytes=filter_options[0])
484+
351485

352486
class Zfp(FilterBase):
353487
"""``h5py.Group.create_dataset``'s compression arguments for using ZFP filter.
@@ -823,6 +957,19 @@ def __init__(self, clevel: int = 3):
823957
raise ValueError("clevel must be in the range [1, 22]")
824958
self.filter_options = (clevel,)
825959

960+
@classmethod
961+
def from_options(cls, filter_options: tuple[int, ...]) -> Zstd:
962+
"""Returns compression arguments from HDF5 compression filters options
963+
964+
:param filter_options: Expected format: (clevel,)
965+
:raises ValueError: Unsupported filter_options
966+
"""
967+
if len(filter_options) != 1:
968+
raise ValueError(
969+
f"Expected 1 value in filter_options, got {len(filter_options)}"
970+
)
971+
return cls(clevel=filter_options[0])
972+
826973

827974
FILTER_CLASSES: Tuple[type[FilterBase], ...] = (
828975
Bitshuffle,

src/hdf5plugin/_utils.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,20 @@ def get_filters(
230230
return tuple(filter_classes)
231231

232232

233+
def filter_from_options(filter_id: int, filter_options: tuple[int, ...]) -> FilterBase:
234+
"""Returns corresponding compression filter configuration instance.
235+
236+
:param filter_id: HDF5 compression filter ID
237+
:param filter_options: Compression filter configuration as stored in HDF5 datasets
238+
:raises ValueError: Unsupported or invalid filter_id, filter_options combination
239+
"""
240+
for filter_cls in FILTER_CLASSES:
241+
if filter_id == filter_cls.filter_id:
242+
return filter_cls.from_options(filter_options)
243+
244+
raise ValueError(f"Unsupported filter id: {filter_id}")
245+
246+
233247
def register(
234248
filters: int | str | tuple[int | str, ...] = tuple(FILTERS.keys()),
235249
force: bool = True,

0 commit comments

Comments
 (0)