Skip to content

Commit be53f9c

Browse files
authored
Work around bitshuffle if not available. (#130)
* Work around bitshuffle if not available. * Update pytest to filter platform.
1 parent c0df490 commit be53f9c

File tree

2 files changed

+58
-18
lines changed

2 files changed

+58
-18
lines changed

src/ess/nmx/nexus.py

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
import pathlib
55
import warnings
66
from collections.abc import Callable, Generator
7-
from functools import partial
7+
from functools import partial, wraps
88
from typing import Any, TypeVar
99

10-
import bitshuffle.h5
1110
import h5py
1211
import numpy as np
1312
import sciline as sl
@@ -34,7 +33,7 @@ def _create_dataset_from_var(
3433
name: str,
3534
long_name: str | None = None,
3635
compression: str | None = None,
37-
compression_opts: int | None = None,
36+
compression_opts: int | tuple[int, int] | None = None,
3837
chunks: tuple[int, ...] | int | bool | None = None,
3938
dtype: Any = None,
4039
) -> h5py.Dataset:
@@ -57,22 +56,47 @@ def _create_dataset_from_var(
5756
return dataset
5857

5958

60-
_create_compressed_dataset = partial(
61-
_create_dataset_from_var,
62-
compression=bitshuffle.h5.H5FILTER,
63-
compression_opts=(0, bitshuffle.h5.H5_COMPRESS_LZ4),
64-
)
65-
"""Create dataset with compression options.
59+
@wraps(_create_dataset_from_var)
60+
def _create_compressed_dataset(*args, **kwargs):
61+
"""Create dataset with compression options.
62+
63+
It will try to use ``bitshuffle`` for compression if available.
64+
Otherwise, it will fall back to ``gzip`` compression.
6665
67-
[``Bitshuffle/LZ4``](https://github.com/kiyo-masui/bitshuffle) is used for convenience.
68-
Since ``Dectris`` uses it for their Nexus file compression, it is compatible with DIALS.
69-
``Bitshuffle/LZ4`` tends to give similar results to
70-
GZIP and other compression algorithms with better performance.
71-
A naive implementation of bitshuffle/LZ4 compression,
72-
shown in [issue #124](https://github.com/scipp/essnmx/issues/124),
73-
led to 80% file reduction (365 MB vs 1.8 GB).
66+
[``Bitshuffle/LZ4``](https://github.com/kiyo-masui/bitshuffle)
67+
is used for convenience.
68+
Since ``Dectris`` uses it for their Nexus file compression,
69+
it is compatible with DIALS.
70+
``Bitshuffle/LZ4`` tends to give similar results to
71+
GZIP and other compression algorithms with better performance.
72+
A naive implementation of bitshuffle/LZ4 compression,
73+
shown in [issue #124](https://github.com/scipp/essnmx/issues/124),
74+
led to 80% file reduction (365 MB vs 1.8 GB).
7475
75-
"""
76+
"""
77+
try:
78+
import bitshuffle.h5
79+
80+
compression_filter = bitshuffle.h5.H5FILTER
81+
default_compression_opts = (0, bitshuffle.h5.H5_COMPRESS_LZ4)
82+
except ImportError:
83+
warnings.warn(
84+
UserWarning(
85+
"Could not find the bitshuffle.h5 module from bitshuffle package. "
86+
"The bitshuffle package is not installed or only partially installed. "
87+
"Exporting to NeXus files with bitshuffle compression is not possible."
88+
),
89+
stacklevel=2,
90+
)
91+
compression_filter = "gzip"
92+
default_compression_opts = 4
93+
94+
return _create_dataset_from_var(
95+
*args,
96+
**kwargs,
97+
compression=compression_filter,
98+
compression_opts=default_compression_opts,
99+
)
76100

77101

78102
def _create_root_data_entry(file_obj: h5py.File) -> h5py.Group:

tests/exporter_test.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ def reduced_data() -> NMXReducedDataGroup:
5454
)
5555

5656

57+
def _is_bitshuffle_available() -> bool:
58+
import platform
59+
60+
return not (
61+
platform.machine().startswith("arm") or platform.platform().startswith('win')
62+
)
63+
64+
5765
def test_mcstas_reduction_export_to_bytestream(
5866
reduced_data: NMXReducedDataGroup,
5967
) -> None:
@@ -75,7 +83,15 @@ def test_mcstas_reduction_export_to_bytestream(
7583
with pytest.warns(
7684
DeprecationWarning, match='Please use ``export_as_nxlauetof`` instead.'
7785
):
78-
export_as_nexus(reduced_data, bio)
86+
if not _is_bitshuffle_available():
87+
# bitshuffle does not build correctly on Windows and ARM machines
88+
# We are keeping this test here to catch when it builds correctly
89+
# in the future.
90+
with pytest.warns(UserWarning, match='bitshuffle.h5'):
91+
export_as_nexus(reduced_data, bio)
92+
else:
93+
export_as_nexus(reduced_data, bio)
94+
7995
with h5py.File(bio, 'r') as f:
8096
assert 'NMX_data' in f
8197
nmx_data: h5py.Group = f.require_group('NMX_data')

0 commit comments

Comments
 (0)