From bb1554c3eb3b42161288bbaec67b849c573eaa07 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Mon, 15 Aug 2022 15:08:06 +0100 Subject: [PATCH 01/13] Test minimal installation without hyperspy --- .github/workflows/tests.yml | 44 +++++++++++++++++++-------- pyproject.toml | 5 ++- rsciio/digital_micrograph/api.py | 2 -- rsciio/tests/test_import.py | 52 ++++++++++++++++++++++++++++++++ rsciio/utils/skimage_exposure.py | 9 +++--- setup.py | 3 ++ 6 files changed, 95 insertions(+), 20 deletions(-) create mode 100644 rsciio/tests/test_import.py diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c3b8f74c8..1258b1085 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,26 +14,27 @@ jobs: matrix: os: [ubuntu, windows, macos] PYTHON_VERSION: ['3.8', '3.9'] - PIP_SELECTOR: ['[all, tests]'] + LABEL: [''] include: # test oldest supported version of main dependencies on python 3.6 - os: ubuntu PYTHON_VERSION: '3.7' - OLDEST_SUPPORTED_VERSION: true DEPENDENCIES: matplotlib==3.1.3 numpy==1.17.1 scipy==1.1 imagecodecs==2020.1.31 tifffile==2020.2.16 dask==2.11.0 distributed==2.11.0 numba==0.52 - PIP_SELECTOR: '[all, tests]' - LABEL: -oldest + LABEL: '-oldest' # test minimum requirement - os: ubuntu PYTHON_VERSION: '3.8' - PIP_SELECTOR: '[tests]' - LABEL: -minimum + LABEL: '-minimum' + - os: ubuntu + PYTHON_VERSION: '3.8' + LABEL: '-minimum-wo-hyperspy' + - os: ubuntu + PYTHON_VERSION: '3.8' + LABEL: '-wo-hyperspy' - os: ubuntu PYTHON_VERSION: '3.7' - PIP_SELECTOR: '[all, tests]' - os: ubuntu PYTHON_VERSION: '3.10' - PIP_SELECTOR: '[all, tests]' steps: - uses: actions/checkout@v3 @@ -43,24 +44,43 @@ jobs: with: python-version: ${{ matrix.PYTHON_VERSION }} + - name: Set Environment Variable + shell: bash + # Set PIP_SELECTOR and PYTEST_ARGS environment variable + # depending on matrix.LABEL + run: | + if [[ -n "${{ matrix.LABEL }}" && "${{ matrix.LABEL }}" == *"minimum"* ]]; then + PIP_SELECTOR="[tests]" + else + PIP_SELECTOR="[all, tests]" + fi + echo "PIP_SELECTOR=${PIP_SELECTOR}" >> $GITHUB_ENV + + if [[ -n "${{ matrix.LABEL }}" && "${{ matrix.LABEL }}" == *"wo-hyperspy"* ]]; then + PYTEST_ARGS="--pyargs rsciio.tests.test_import -m no_hyperspy" + else + PYTEST_ARGS="--pyargs rsciio --reruns 3 -n 2 --cov=. --cov-report=xml" + fi + echo "PYTEST_ARGS=${PYTEST_ARGS}" >> $GITHUB_ENV + - name: Display version run: | python --version pip --version - name: Install oldest supported version - if: ${{ matrix.OLDEST_SUPPORTED_VERSION }} + if: contains(matrix.LABEL, 'oldest') run: | pip install ${{ matrix.DEPENDENCIES }} - name: Install shell: bash run: | - pip install --upgrade -e .'${{ matrix.PIP_SELECTOR }}' + pip install --upgrade -e .'${{ env.PIP_SELECTOR }}' - name: Install (HyperSpy dev) + if: "!contains(matrix.LABEL, 'wo-hyperspy')" # Need to install hyperspy dev until hyperspy 2.0 is released - shell: bash run: | pip install https://github.com/hyperspy/hyperspy/archive/refs/heads/RELEASE_next_major.zip @@ -70,7 +90,7 @@ jobs: - name: Run test suite run: | - pytest --pyargs rsciio --reruns 3 -n 2 --cov=. --cov-report=xml + pytest ${{ env.PYTEST_ARGS }} - name: Upload coverage to Codecov if: ${{ always() }} diff --git a/pyproject.toml b/pyproject.toml index 182919c60..6e8de4dba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,13 +3,16 @@ requires = ["setuptools>=49.0", "wheel", "cython", "pyyaml"] build-backend = "setuptools.build_meta:__legacy__" [tool.pytest.ini_options] -# Note we may need to use `-n 2` argument for pytest-xdist on CI +# Note we may need to use `-n 2` argument for pytest-xdist on CI # due to https://github.com/pytest-dev/pytest-xdist/issues/9. addopts = "-ra -n auto --dist loadfile" minversion = "6.0" testpaths = [ "rsciio/tests", ] +markers = [ + "no_hyperspy: marks tests to run without hyperspy", +] [tool.towncrier] package = "rsciio" diff --git a/rsciio/digital_micrograph/api.py b/rsciio/digital_micrograph/api.py index aa3246674..a10144dfa 100644 --- a/rsciio/digital_micrograph/api.py +++ b/rsciio/digital_micrograph/api.py @@ -26,12 +26,10 @@ import dateutil.parser import numpy as np -import traits.api as t from copy import deepcopy import rsciio.utils.utils_readfile as iou from rsciio.exceptions import DM3TagIDError, DM3DataTypeError, DM3TagTypeError -import rsciio.utils.tools from box import Box diff --git a/rsciio/tests/test_import.py b/rsciio/tests/test_import.py new file mode 100644 index 000000000..454494c62 --- /dev/null +++ b/rsciio/tests/test_import.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2007-2022 The HyperSpy developers +# +# This file is part of RosettaSciIO. +# +# RosettaSciIO is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# RosettaSciIO is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with RosettaSciIO. If not, see . + +import importlib + +import pytest + + +@pytest.mark.no_hyperspy +def test_import_version(): + from rsciio import __version__ + + +@pytest.mark.no_hyperspy +def test_import_minimal_no_hyperspy(): + from rsciio import IO_PLUGINS + + for plugin in IO_PLUGINS: + if plugin["format_name"] not in [ + "Blockfile", + "Electron Microscopy Data (EMD)", + "image", + "MRCZ", + "Phenom Element Identification (ELID)", + "TIFF", + "TVIPS", + "USID", + "ZSpy", + ]: + importlib.import_module(plugin["api"]) + + +def test_import_all(): + from rsciio import IO_PLUGINS + + for plugin in IO_PLUGINS: + importlib.import_module(plugin["api"]) diff --git a/rsciio/utils/skimage_exposure.py b/rsciio/utils/skimage_exposure.py index fe18d2636..da868e895 100644 --- a/rsciio/utils/skimage_exposure.py +++ b/rsciio/utils/skimage_exposure.py @@ -1,11 +1,10 @@ """skimage's `rescale_intensity` that takes and returns dask arrays. """ -import numpy as np -import dask.array as da - +import warnings -from skimage.exposure.exposure import intensity_range, _output_dtype, DTYPE_RANGE +import numpy as np +from skimage.exposure.exposure import intensity_range, _output_dtype def rescale_intensity(image, in_range="image", out_range="dtype"): @@ -111,7 +110,7 @@ def rescale_intensity(image, in_range="image", out_range="dtype"): ) if np.any(np.isnan([imin, imax, omin, omax])): - utils.warn( + warnings.warn( "One or more intensity levels are NaN. Rescaling will broadcast " "NaN to the full image. Provide intensity levels yourself to " "avoid this. E.g. with np.nanmin(image), np.nanmax(image).", diff --git a/setup.py b/setup.py index 1e0b90ea2..759098441 100644 --- a/setup.py +++ b/setup.py @@ -154,6 +154,7 @@ def run(self): install_requires = [ "dask[array]>=2.11", + "python-dateutil", "h5py>=2.3", "imageio", "numba>=0.52", @@ -166,9 +167,11 @@ def run(self): ] extras_require = { + "blockfile": ["scikit-image"], "mrcz": ["blosc>=1.5", "mrcz>=0.3.6"], "scalebar_export": ["matplotlib>=3.1.3"], "tiff": ["tifffile>=2020.2.16", "imagecodecs>=2020.1.31"], + "zspy": ['zarr'], "tests": [ "pytest>=3.6", "pytest-xdist", From a6a64b4ce6b562eced862270b5f663f6931d3b3c Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Mon, 15 Aug 2022 16:13:09 +0100 Subject: [PATCH 02/13] Test import submodules with minimal dependencies --- rsciio/image/api.py | 9 ++++++++- rsciio/tests/test_image.py | 30 ++++++++++++++++++------------ rsciio/tests/test_import.py | 37 ++++++++++++++++++++++++++++++++++++- setup.py | 3 ++- 4 files changed, 64 insertions(+), 15 deletions(-) diff --git a/rsciio/image/api.py b/rsciio/image/api.py index 1cdf45da1..f68be186a 100644 --- a/rsciio/image/api.py +++ b/rsciio/image/api.py @@ -20,7 +20,6 @@ import logging from imageio import imread, imwrite -from matplotlib.figure import Figure from rsciio.utils.tools import _UREG @@ -105,6 +104,14 @@ def file_writer( ) if scalebar or output_size or imshow_kwds: + try: + from matplotlib.figure import Figure + except ImportError: + raise ValueError( + "Using the `output_size`, `imshow_kwds` arguments or " + "exporting with a scalebar requires the matplotlib library." + ) + dpi = 100 if imshow_kwds is None: diff --git a/rsciio/tests/test_image.py b/rsciio/tests/test_image.py index b35d9981a..158b7e2e1 100644 --- a/rsciio/tests/test_image.py +++ b/rsciio/tests/test_image.py @@ -22,14 +22,6 @@ import hyperspy.api as hs -try: - from matplotlib_scalebar.scalebar import ScaleBar - - matplotlib_scalebar_installed = True -except ImportError: # pragma: no cover - matplotlib_scalebar_installed = False - - @pytest.mark.parametrize(("dtype"), ["uint8", "uint32"]) @pytest.mark.parametrize(("ext"), ["png", "bmp", "gif", "jpg"]) def test_save_load_cycle_grayscale(dtype, ext, tmp_path): @@ -85,13 +77,14 @@ def test_save_load_cycle_kwds(dtype, ext, tmp_path): @pytest.mark.parametrize(("ext"), ["png", "bmp", "gif", "jpg"]) def test_export_scalebar(ext, tmp_path): + pytest.importorskip("matplotlib_scalebar") data = np.arange(1e6).reshape((1000, 1000)) s = hs.signals.Signal2D(data) s.axes_manager[0].units = "nm" s.axes_manager[1].units = "nm" filename = tmp_path / f"test_scalebar_export.{ext}" - if ext in ["bmp", "gif"] and matplotlib_scalebar_installed: + if ext in ["bmp", "gif"]: with pytest.raises(ValueError): s.save(filename, scalebar=True) with pytest.raises(ValueError): @@ -136,10 +129,8 @@ def test_non_uniform(tmp_path): s.save(filename) -@pytest.mark.skipif( - not matplotlib_scalebar_installed, reason="matplotlib_scalebar is not installed" -) def test_export_scalebar_different_scale_units(tmp_path): + pytest.importorskip("matplotlib_scalebar") pixels = 16 s = hs.signals.Signal2D(np.arange(pixels**2).reshape((pixels, pixels))) s.axes_manager[0].scale = 2 @@ -205,3 +196,18 @@ def test_save_image_navigation(tmp_path): fname = tmp_path / "test_save_image_navigation.jpg" s.T.save(fname, scalebar=True) + + +def test_error_library_no_installed(tmp_path): + s = hs.signals.Signal2D(np.arange(128 * 128).reshape(128, 128)) + + try: + import matplotlib + except: + # When matplotlib is not installed, raises an error to inform user + # that matplotlib is necessary + with pytest.raises(ValueError): + s.save(tmp_path / "test_image_error.jpg", output_size=64) + + with pytest.raises(ValueError): + s.save(tmp_path / "test_image_error.jpg", imshow_kwds={"a": "b"}) diff --git a/rsciio/tests/test_import.py b/rsciio/tests/test_import.py index 454494c62..ba2067022 100644 --- a/rsciio/tests/test_import.py +++ b/rsciio/tests/test_import.py @@ -27,7 +27,7 @@ def test_import_version(): @pytest.mark.no_hyperspy -def test_import_minimal_no_hyperspy(): +def test_import_with_minimal_dependencies_no_hyperspy(): from rsciio import IO_PLUGINS for plugin in IO_PLUGINS: @@ -48,5 +48,40 @@ def test_import_minimal_no_hyperspy(): def test_import_all(): from rsciio import IO_PLUGINS + plugin_name_to_remove = [] + + # Remove plugins which requires optional dependencies, which is installed + try: + import skimage + except: + plugin_name_to_remove.append("Blockfile") + + try: + import mrcz + except: + plugin_name_to_remove.append("MRCZ") + + try: + import tifffile + except: + plugin_name_to_remove.append("TIFF") + + try: + import pyUSID + except: + plugin_name_to_remove.append("USID") + + try: + import zarr + except: + plugin_name_to_remove.append("ZSpy") + + IO_PLUGINS = list( + filter( + lambda plugin: plugin["format_name"] not in plugin_name_to_remove, + IO_PLUGINS, + ) + ) + for plugin in IO_PLUGINS: importlib.import_module(plugin["api"]) diff --git a/setup.py b/setup.py index 759098441..df72c01de 100644 --- a/setup.py +++ b/setup.py @@ -169,8 +169,9 @@ def run(self): extras_require = { "blockfile": ["scikit-image"], "mrcz": ["blosc>=1.5", "mrcz>=0.3.6"], - "scalebar_export": ["matplotlib>=3.1.3"], + "scalebar_export": ["matplotlib-scalebar", "matplotlib>=3.1.3"], "tiff": ["tifffile>=2020.2.16", "imagecodecs>=2020.1.31"], + "usid": ["pyUSID"], "zspy": ['zarr'], "tests": [ "pytest>=3.6", From e24e6253ed158f1e964cdcb67490857171194e88 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Tue, 16 Aug 2022 10:29:51 +0100 Subject: [PATCH 03/13] Use importorskip to skip tests using hyperspy --- rsciio/tests/test_blockfile.py | 12 +- rsciio/tests/test_bruker.py | 52 ++--- rsciio/tests/test_de5.py | 4 +- rsciio/tests/test_dens.py | 3 +- rsciio/tests/test_dm3.py | 56 ++--- rsciio/tests/test_dm_stackbuilder_plugin.py | 7 +- rsciio/tests/test_edax.py | 44 ++-- rsciio/tests/test_emd.py | 164 +++++++-------- rsciio/tests/test_emd_prismatic.py | 4 +- rsciio/tests/test_empad.py | 4 +- rsciio/tests/test_fei.py | 80 +++---- rsciio/tests/test_hdf5.py | 221 ++++++++++---------- rsciio/tests/test_image.py | 26 ++- rsciio/tests/test_import.py | 1 - rsciio/tests/test_impulse.py | 4 +- rsciio/tests/test_io.py | 34 ++- rsciio/tests/test_jeol.py | 5 +- rsciio/tests/test_mrcz.py | 32 ++- rsciio/tests/test_msa.py | 22 +- rsciio/tests/test_nexus_hdf.py | 68 +++--- rsciio/tests/test_panta_rhei.py | 4 +- rsciio/tests/test_phenom.py | 3 +- rsciio/tests/test_protochips.py | 3 +- rsciio/tests/test_ripple.py | 30 +-- rsciio/tests/test_semper_unf.py | 57 +++-- rsciio/tests/test_sur.py | 20 +- rsciio/tests/test_tiff.py | 38 +++- rsciio/tests/test_tvips.py | 11 +- rsciio/tests/test_usid.py | 3 +- rsciio/tests/test_zspy.py | 32 ++- rsciio/utils/array.py | 39 ++++ rsciio/utils/rgb_tools.py | 2 +- setup.py | 2 +- 33 files changed, 596 insertions(+), 491 deletions(-) create mode 100644 rsciio/utils/array.py diff --git a/rsciio/tests/test_blockfile.py b/rsciio/tests/test_blockfile.py index 769d46ce1..751e75dc3 100644 --- a/rsciio/tests/test_blockfile.py +++ b/rsciio/tests/test_blockfile.py @@ -23,14 +23,15 @@ import warnings import numpy as np -from skimage.exposure import rescale_intensity import pytest -import hyperspy.api as hs +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + +from hyperspy.misc.test_utils import assert_deep_almost_equal + from rsciio.blockfile.api import get_default_header from rsciio.utils.tools import sarray2dict from rsciio.utils.date_time_tools import serial_date_to_ISO_format -from hyperspy.misc.test_utils import assert_deep_almost_equal try: WindowsError @@ -370,9 +371,12 @@ def test_crop_lims(save_path, fake_signal): def test_tuple_limits(save_path, fake_signal): + skimage = pytest.importorskip("skimage", reason="scikit-image not installed") fake_signal.save(save_path, intensity_scaling=(5, 200), overwrite=True) sig_reload = hs.load(save_path) - compare = rescale_intensity(fake_signal.data, in_range=(5, 200), out_range=np.uint8) + compare = skimage.exposure.rescale_intensity( + fake_signal.data, in_range=(5, 200), out_range=np.uint8 + ) np.testing.assert_allclose(sig_reload.data, compare) diff --git a/rsciio/tests/test_bruker.py b/rsciio/tests/test_bruker.py index 922c5d453..fde275655 100644 --- a/rsciio/tests/test_bruker.py +++ b/rsciio/tests/test_bruker.py @@ -4,9 +4,10 @@ import numpy as np import pytest -from hyperspy import __version__ as hs_version -from hyperspy import signals -from hyperspy.io import load +from rsciio.exceptions import VisibleDeprecationWarning + +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + from hyperspy.misc.test_utils import assert_deep_almost_equal test_files = [ @@ -26,12 +27,12 @@ def test_load_16bit(): - # test bcf from hyperspy load function level + # test bcf from hyperspy hs.load function level # some of functions can be not covered # it cant use cython parsing implementation, as it is not compiled filename = os.path.join(my_path, "bruker_data", test_files[0]) print("testing bcf instructively packed 16bit...") - s = load(filename) + s = hs.load(filename) bse, hype = s # Bruker saves all images in true 16bit: assert bse.data.dtype == np.uint16 @@ -46,7 +47,7 @@ def test_load_16bit(): def test_load_16bit_reduced(): filename = os.path.join(my_path, "bruker_data", test_files[0]) print("testing downsampled 16bit bcf...") - s = load(filename, downsample=4, cutoff_at_kV=10) + s = hs.load(filename, downsample=4, cutoff_at_kV=10) bse, hype = s # sem images are never downsampled assert bse.data.shape == (30, 30) @@ -62,14 +63,14 @@ def test_load_16bit_reduced(): def test_load_16bit_cutoff_zealous(): filename = os.path.join(my_path, "bruker_data", test_files[0]) print("testing downsampled 16bit bcf with cutoff_at_kV=zealous...") - hype = load(filename, cutoff_at_kV="zealous", select_type="spectrum_image") + hype = hs.load(filename, cutoff_at_kV="zealous", select_type="spectrum_image") assert hype.data.shape == (30, 30, 2048) def test_load_16bit_cutoff_auto(): filename = os.path.join(my_path, "bruker_data", test_files[0]) print("testing downsampled 16bit bcf with cutoff_at_kV=auto...") - hype = load(filename, cutoff_at_kV="auto", select_type="spectrum_image") + hype = hs.load(filename, cutoff_at_kV="auto", select_type="spectrum_image") assert hype.data.shape == (30, 30, 2048) @@ -77,7 +78,7 @@ def test_load_8bit(): for bcffile in test_files[1:3]: filename = os.path.join(my_path, "bruker_data", bcffile) print("testing simple 8bit bcf...") - s = load(filename) + s = hs.load(filename) bse, hype = s[0], s[-1] # Bruker saves all images in true 16bit: assert bse.data.dtype == np.uint16 @@ -88,11 +89,10 @@ def test_load_8bit(): def test_hyperspy_wrap(): filename = os.path.join(my_path, "bruker_data", test_files[0]) print("testing bcf wrap to hyperspy signal...") - from rsciio.exceptions import VisibleDeprecationWarning with pytest.warns(VisibleDeprecationWarning): - hype = load(filename, select_type="spectrum") - hype = load(filename, select_type="spectrum_image") + hype = hs.load(filename, select_type="spectrum") + hype = hs.load(filename, select_type="spectrum_image") np.testing.assert_allclose(hype.axes_manager[0].scale, 1.66740910949362, atol=1e-12) np.testing.assert_allclose(hype.axes_manager[1].scale, 1.66740910949362, atol=1e-12) assert hype.axes_manager[1].units == "µm" @@ -132,7 +132,7 @@ def test_hyperspy_wrap(): "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.bruker.api", } }, @@ -203,7 +203,7 @@ def test_hyperspy_wrap(): def test_hyperspy_wrap_downsampled(): filename = os.path.join(my_path, "bruker_data", test_files[0]) print("testing bcf wrap to hyperspy signal...") - hype = load(filename, select_type="spectrum_image", downsample=5) + hype = hs.load(filename, select_type="spectrum_image", downsample=5) np.testing.assert_allclose( hype.axes_manager[0].scale, 8.337045547468101, atol=1e-12 ) @@ -215,30 +215,30 @@ def test_hyperspy_wrap_downsampled(): def test_get_mode(): filename = os.path.join(my_path, "bruker_data", test_files[0]) - s = load(filename, select_type="spectrum_image", instrument="SEM") + s = hs.load(filename, select_type="spectrum_image", instrument="SEM") assert s.metadata.Signal.signal_type == "EDS_SEM" - assert isinstance(s, signals.EDSSEMSpectrum) + assert isinstance(s, hs.signals.EDSSEMSpectrum) filename = os.path.join(my_path, "bruker_data", test_files[0]) - s = load(filename, select_type="spectrum_image", instrument="TEM") + s = hs.load(filename, select_type="spectrum_image", instrument="TEM") assert s.metadata.Signal.signal_type == "EDS_TEM" - assert isinstance(s, signals.EDSTEMSpectrum) + assert isinstance(s, hs.signals.EDSTEMSpectrum) filename = os.path.join(my_path, "bruker_data", test_files[0]) - s = load(filename, select_type="spectrum_image") + s = hs.load(filename, select_type="spectrum_image") assert s.metadata.Signal.signal_type == "EDS_SEM" - assert isinstance(s, signals.EDSSEMSpectrum) + assert isinstance(s, hs.signals.EDSSEMSpectrum) filename = os.path.join(my_path, "bruker_data", test_files[3]) - s = load(filename, select_type="spectrum_image") + s = hs.load(filename, select_type="spectrum_image") assert s.metadata.Signal.signal_type == "EDS_TEM" - assert isinstance(s, signals.EDSTEMSpectrum) + assert isinstance(s, hs.signals.EDSTEMSpectrum) def test_wrong_file(): filename = os.path.join(my_path, "bruker_data", "Nope.bcf") with pytest.raises(TypeError): - load(filename) + hs.load(filename) def test_fast_bcf(): @@ -280,14 +280,14 @@ def test_decimal_regex(): def test_all_spx_loads(): for spxfile in spx_files: filename = os.path.join(my_path, "bruker_data", spxfile) - s = load(filename) + s = hs.load(filename) assert s.data.dtype == np.uint64 assert s.metadata.Signal.signal_type == "EDS_SEM" def test_stand_alone_spx(): filename = os.path.join(my_path, "bruker_data", "bruker_nano.spx") - s = load(filename) + s = hs.load(filename) assert s.metadata.Sample.elements == ["Fe", "S", "Cu"] assert s.metadata.Acquisition_instrument.SEM.Detector.EDS.live_time == 7.385 @@ -298,6 +298,6 @@ def test_bruker_XRF(): filename = os.path.join( my_path, "bruker_data", "bruker_m6_jetstream_file_example.spx" ) - s = load(filename) + s = hs.load(filename) assert s.metadata.Acquisition_instrument.TEM.Detector.EDS.live_time == 28.046 assert s.metadata.Acquisition_instrument.TEM.beam_energy == 50 diff --git a/rsciio/tests/test_de5.py b/rsciio/tests/test_de5.py index 4e6fc383d..b17a87a85 100644 --- a/rsciio/tests/test_de5.py +++ b/rsciio/tests/test_de5.py @@ -21,8 +21,10 @@ # National Lab (see https://emdatasets.com/ for more information). # NOT to be confused with the FEI EMD format which was developed later. -import hyperspy.api as hs import numpy as np +import pytest + +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") def test_de5_write_load_cycle(tmp_path): diff --git a/rsciio/tests/test_dens.py b/rsciio/tests/test_dens.py index 7ae05561f..59fa6ef9c 100644 --- a/rsciio/tests/test_dens.py +++ b/rsciio/tests/test_dens.py @@ -22,7 +22,8 @@ import numpy as np import pytest -import hyperspy.api as hs +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + dirpath = os.path.dirname(__file__) diff --git a/rsciio/tests/test_dm3.py b/rsciio/tests/test_dm3.py index 6cc1d626f..01be6ca4b 100644 --- a/rsciio/tests/test_dm3.py +++ b/rsciio/tests/test_dm3.py @@ -23,12 +23,12 @@ import numpy as np import pytest -from hyperspy import __version__ as hs_version -from hyperspy.io import load from rsciio.digital_micrograph.api import DigitalMicrographReader, ImageObject -from hyperspy.signals import Signal1D, Signal2D from rsciio.tests.generate_dm_testing_files import dm3_data_types, dm4_data_types +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + + MY_PATH = os.path.dirname(__file__) @@ -77,7 +77,7 @@ def test_missing_tag(): fname = os.path.join( MY_PATH, "dm3_2D_data", "test_diffraction_pattern_tags_removed.dm3" ) - s = load(fname) + s = hs.load(fname) md = s.metadata np.testing.assert_allclose(md.Acquisition_instrument.TEM.beam_energy, 200.0) np.testing.assert_allclose(md.Acquisition_instrument.TEM.Camera.exposure, 0.2) @@ -88,7 +88,7 @@ def test_missing_tag(): def test_read_TEM_metadata(): fname = os.path.join(MY_PATH, "tiff_files", "test_dm_image_um_unit.dm3") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Acquisition_instrument.TEM.acquisition_mode == "TEM" np.testing.assert_allclose(md.Acquisition_instrument.TEM.beam_energy, 200.0) @@ -105,7 +105,7 @@ def test_read_TEM_metadata(): def test_read_Diffraction_metadata(): fname = os.path.join(MY_PATH, "dm3_2D_data", "test_diffraction_pattern.dm3") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Acquisition_instrument.TEM.acquisition_mode == "TEM" np.testing.assert_allclose(md.Acquisition_instrument.TEM.beam_energy, 200.0) @@ -122,7 +122,7 @@ def test_read_Diffraction_metadata(): def test_read_STEM_metadata(): fname = os.path.join(MY_PATH, "dm3_2D_data", "test_STEM_image.dm3") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Acquisition_instrument.TEM.acquisition_mode == "STEM" np.testing.assert_allclose(md.Acquisition_instrument.TEM.beam_energy, 200.0) @@ -140,7 +140,7 @@ def test_read_STEM_metadata(): def test_read_EELS_metadata(): fname = os.path.join(MY_PATH, "dm3_1D_data", "test-EELS_spectrum.dm3") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Acquisition_instrument.TEM.acquisition_mode == "STEM" np.testing.assert_allclose(md.Acquisition_instrument.TEM.beam_energy, 200.0) @@ -187,7 +187,7 @@ def test_read_EELS_metadata(): def test_read_SI_metadata(): fname = os.path.join(MY_PATH, "dm4_3D_data", "EELS_SI.dm4") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Acquisition_instrument.TEM.acquisition_mode == "STEM" assert md.General.date == "2019-05-14" @@ -209,7 +209,7 @@ def test_read_SI_metadata(): def test_read_EDS_metadata(): fname = os.path.join(MY_PATH, "dm3_1D_data", "test-EDS_spectrum.dm3") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Acquisition_instrument.TEM.acquisition_mode == "STEM" np.testing.assert_allclose( @@ -251,7 +251,7 @@ def test_read_EDS_metadata(): def test_read_MonoCL_pmt_metadata(): fname = os.path.join(MY_PATH, "dm4_1D_data", "test-MonoCL_spectrum-pmt.dm4") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Signal.signal_type == "CL" assert md.Signal.format == "Spectrum" @@ -273,7 +273,7 @@ def test_read_MonoCL_pmt_metadata(): def test_read_MonarcCL_pmt_metadata(): fname = os.path.join(MY_PATH, "dm4_1D_data", "test-MonarcCL_spectrum-pmt.dm4") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Signal.signal_type == "CL" assert md.Signal.format == "Spectrum" @@ -295,7 +295,7 @@ def test_read_MonarcCL_pmt_metadata(): def test_read_MonoCL_ccd_metadata(): fname = os.path.join(MY_PATH, "dm4_1D_data", "test-MonoCL_spectrum-ccd.dm4") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Signal.signal_type == "CL" assert md.Signal.format == "Spectrum" @@ -330,7 +330,7 @@ def test_read_MonoCL_ccd_metadata(): def test_read_MonarcCL_ccd_metadata(): fname = os.path.join(MY_PATH, "dm4_1D_data", "test-MonarcCL_spectrum-ccd.dm4") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Signal.signal_type == "CL" assert md.Signal.format == "Spectrum" @@ -366,7 +366,7 @@ def test_read_MonarcCL_ccd_metadata(): def test_read_MonoCL_SI_metadata(): fname = os.path.join(MY_PATH, "dm4_2D_data", "test-MonoCL_spectrum-SI.dm4") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Signal.signal_type == "CL" assert md.Signal.format == "Spectrum image" @@ -412,7 +412,7 @@ def test_read_MonoCL_SI_metadata(): def test_read_MonarcCL_SI_metadata(): fname = os.path.join(MY_PATH, "dm4_2D_data", "test-MonarcCL_spectrum-SI.dm4") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Signal.signal_type == "CL" assert md.Signal.format == "Spectrum image" @@ -455,7 +455,7 @@ def test_read_MonarcCL_SI_metadata(): def test_read_MonarcCL_image_metadata(): fname = os.path.join(MY_PATH, "dm4_2D_data", "test-MonarcCL_mono-image.dm4") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Signal.signal_type == "CL" assert md.Signal.quantity == "Intensity (counts)" @@ -483,23 +483,23 @@ def test_location(): "Fei HAADF-MX_location.dm3", "Fei HAADF-UK_location.dm3", ] - s = load(os.path.join(MY_PATH, "dm3_locale", fname_list[0])) + s = hs.load(os.path.join(MY_PATH, "dm3_locale", fname_list[0])) assert s.metadata.General.date == "2016-08-27" assert s.metadata.General.time == "20:54:33" - s = load(os.path.join(MY_PATH, "dm3_locale", fname_list[1])) + s = hs.load(os.path.join(MY_PATH, "dm3_locale", fname_list[1])) assert s.metadata.General.date == "2016-08-27" assert s.metadata.General.time == "20:55:20" - s = load(os.path.join(MY_PATH, "dm3_locale", fname_list[2])) + s = hs.load(os.path.join(MY_PATH, "dm3_locale", fname_list[2])) assert s.metadata.General.date == "2016-08-27" # assert_equal(s.metadata.General.time, "20:55:20") # MX not working - s = load(os.path.join(MY_PATH, "dm3_locale", fname_list[3])) + s = hs.load(os.path.join(MY_PATH, "dm3_locale", fname_list[3])) assert s.metadata.General.date == "2016-08-27" assert s.metadata.General.time == "20:52:30" def test_multi_signal(): fname = os.path.join(MY_PATH, "dm3_2D_data", "multi_signal.dm3") - s = load(fname) + s = hs.load(fname) # Make sure file is read as a list, and exactly two signals are found assert isinstance(s, list) @@ -508,8 +508,8 @@ def test_multi_signal(): s1, s2 = s # First signal is an image, second is a plot - assert isinstance(s1, Signal2D) - assert isinstance(s2, Signal1D) + assert isinstance(s1, hs.signals.Signal2D) + assert isinstance(s2, hs.signals.Signal1D) s1_md_truth = { "_HyperSpy": { @@ -529,7 +529,7 @@ def test_multi_signal(): "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.digital_micrograph.api", } }, @@ -576,7 +576,7 @@ def test_multi_signal(): "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.digital_micrograph.api", } }, @@ -643,7 +643,7 @@ def generate_parameters(): @pytest.mark.parametrize("pdict", generate_parameters()) @pytest.mark.parametrize("lazy", (True, False)) def test_data(pdict, lazy): - s = load(pdict["filename"], lazy=lazy) + s = hs.load(pdict["filename"], lazy=lazy) if lazy: s.compute(close_file=True) key = pdict["key"] @@ -671,5 +671,5 @@ def test_data(pdict, lazy): def test_axes_bug_for_image(): fname = os.path.join(MY_PATH, "dm3_2D_data", "test_STEM_image.dm3") - s = load(fname) + s = hs.load(fname) assert s.axes_manager[1].name == "y" diff --git a/rsciio/tests/test_dm_stackbuilder_plugin.py b/rsciio/tests/test_dm_stackbuilder_plugin.py index 2a6a2a7ff..477151b12 100644 --- a/rsciio/tests/test_dm_stackbuilder_plugin.py +++ b/rsciio/tests/test_dm_stackbuilder_plugin.py @@ -20,14 +20,17 @@ import os import numpy as np -from hyperspy.io import load +import pytest + +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + my_path = os.path.dirname(__file__) class TestStackBuilder: def test_load_stackbuilder_imagestack(self): - image_stack = load( + image_stack = hs.load( os.path.join( my_path, "dm_stackbuilder_plugin", "test_stackbuilder_imagestack.dm3" ) diff --git a/rsciio/tests/test_edax.py b/rsciio/tests/test_edax.py index a08854bbe..dfac3ff69 100644 --- a/rsciio/tests/test_edax.py +++ b/rsciio/tests/test_edax.py @@ -1,3 +1,21 @@ +# -*- coding: utf-8 -*- +# Copyright 2007-2022 The HyperSpy developers +# +# This file is part of RosettaSciIO. +# +# RosettaSciIO is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# RosettaSciIO is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with RosettaSciIO. If not, see . + import gc import hashlib import os @@ -7,10 +25,10 @@ import numpy as np import pytest -import requests -from hyperspy import signals -from hyperspy.io import load +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") +requests = pytest.importorskip("requests", reason="requests not installed") + MY_PATH = os.path.dirname(__file__) ZIPF = os.path.join(MY_PATH, "edax_files.zip") @@ -60,8 +78,8 @@ def teardown_module(): class TestSpcSpectrum_v061_xrf: @classmethod def setup_class(cls): - cls.spc = load(os.path.join(TMP_DIR.name, "spc0_61-ipr333_xrf.spc")) - cls.spc_loadAll = load( + cls.spc = hs.load(os.path.join(TMP_DIR.name, "spc0_61-ipr333_xrf.spc")) + cls.spc_loadAll = hs.load( os.path.join(TMP_DIR.name, "spc0_61-ipr333_xrf.spc"), load_all_spc=True ) @@ -152,7 +170,7 @@ def test_parameters(self): # Testing HyperSpy parameters assert "EDS_SEM" == signal_dict["signal_type"] - assert isinstance(TestSpcSpectrum_v061_xrf.spc, signals.EDSSEMSpectrum) + assert isinstance(TestSpcSpectrum_v061_xrf.spc, hs.signals.EDSSEMSpectrum) def test_axes(self): spc_ax_manager = { @@ -188,8 +206,8 @@ def test_load_all_spc(self): class TestSpcSpectrum_v070_eds: @classmethod def setup_class(cls): - cls.spc = load(os.path.join(TMP_DIR.name, "single_spect.spc")) - cls.spc_loadAll = load( + cls.spc = hs.load(os.path.join(TMP_DIR.name, "single_spect.spc")) + cls.spc_loadAll = hs.load( os.path.join(TMP_DIR.name, "single_spect.spc"), load_all_spc=True ) @@ -254,7 +272,7 @@ def test_parameters(self): # Testing HyperSpy parameters assert "EDS_SEM" == signal_dict["signal_type"] - assert isinstance(TestSpcSpectrum_v070_eds.spc, signals.EDSSEMSpectrum) + assert isinstance(TestSpcSpectrum_v070_eds.spc, hs.signals.EDSSEMSpectrum) def test_axes(self): spc_ax_manager = { @@ -294,7 +312,7 @@ def test_load_all_spc(self): class TestSpdMap_070_eds: @classmethod def setup_class(cls): - cls.spd = load(os.path.join(TMP_DIR.name, "spd_map.spd"), convert_units=True) + cls.spd = hs.load(os.path.join(TMP_DIR.name, "spd_map.spd"), convert_units=True) @classmethod def teardown_class(cls): @@ -369,7 +387,7 @@ def test_parameters(self): # Testing HyperSpy parameters assert "EDS_SEM" == signal_dict["signal_type"] - assert isinstance(TestSpdMap_070_eds.spd, signals.EDSSEMSpectrum) + assert isinstance(TestSpdMap_070_eds.spd, hs.signals.EDSSEMSpectrum) def test_axes(self): spd_ax_manager = { @@ -437,7 +455,7 @@ def test_spc_reading(self): class TestSpdMap_061_xrf: @classmethod def setup_class(cls): - cls.spd = load( + cls.spd = hs.load( os.path.join(TMP_DIR.name, "spc0_61-ipr333_xrf.spd"), convert_units=True ) @@ -516,7 +534,7 @@ def test_parameters(self): # Testing HyperSpy parameters assert "EDS_SEM" == signal_dict["signal_type"] - assert isinstance(TestSpdMap_061_xrf.spd, signals.EDSSEMSpectrum) + assert isinstance(TestSpdMap_061_xrf.spd, hs.signals.EDSSEMSpectrum) def test_axes(self): spd_ax_manager = { diff --git a/rsciio/tests/test_emd.py b/rsciio/tests/test_emd.py index 28301dc18..86e0f3f1b 100644 --- a/rsciio/tests/test_emd.py +++ b/rsciio/tests/test_emd.py @@ -32,16 +32,9 @@ import tempfile import shutil -from hyperspy import __version__ as hs_version -from hyperspy.io import load +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + from hyperspy.misc.test_utils import assert_deep_almost_equal -from hyperspy.signals import ( - BaseSignal, - EDSTEMSpectrum, - Signal1D, - Signal2D, - ComplexSignal2D, -) my_path = os.path.dirname(__file__) @@ -65,27 +58,29 @@ @pytest.mark.parametrize("lazy", (True, False)) def test_signal_3d_loading(lazy): - signal = load(os.path.join(my_path, "emd_files", "example_signal.emd"), lazy=lazy) + signal = hs.load( + os.path.join(my_path, "emd_files", "example_signal.emd"), lazy=lazy + ) if lazy: signal.compute(close_file=True) np.testing.assert_equal(signal.data, data_signal) - assert isinstance(signal, BaseSignal) + assert isinstance(signal, hs.signals.BaseSignal) def test_image_2d_loading(): - signal = load(os.path.join(my_path, "emd_files", "example_image.emd")) + signal = hs.load(os.path.join(my_path, "emd_files", "example_image.emd")) np.testing.assert_equal(signal.data, data_image) - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) def test_spectrum_1d_loading(): - signal = load(os.path.join(my_path, "emd_files", "example_spectrum.emd")) + signal = hs.load(os.path.join(my_path, "emd_files", "example_spectrum.emd")) np.testing.assert_equal(signal.data, data_spectrum) - assert isinstance(signal, Signal1D) + assert isinstance(signal, hs.signals.Signal1D) def test_metadata(): - signal = load(os.path.join(my_path, "emd_files", "example_metadata.emd")) + signal = hs.load(os.path.join(my_path, "emd_files", "example_metadata.emd")) om = signal.original_metadata np.testing.assert_equal(signal.data, data_image) np.testing.assert_equal(signal.metadata.General.title, test_title) @@ -93,7 +88,7 @@ def test_metadata(): np.testing.assert_equal(om.microscope.as_dictionary(), microscope) np.testing.assert_equal(om.sample.as_dictionary(), sample) np.testing.assert_equal(om.comments.as_dictionary(), comments) - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) def test_metadata_with_bytes_string(): @@ -106,18 +101,18 @@ def test_metadata_with_bytes_string(): f.close() assert isinstance(dim1_name, np.bytes_) assert isinstance(dim1_units, np.bytes_) - _ = load(os.path.join(my_path, "emd_files", filename)) + _ = hs.load(os.path.join(my_path, "emd_files", filename)) def test_data_numpy_object_dtype(): filename = os.path.join(my_path, "emd_files", "example_object_dtype_data.emd") - signal = load(filename) + signal = hs.load(filename) np.testing.assert_equal(signal.data, np.array([["a, 2, test1", "a, 2, test1"]])) def test_data_axis_length_1(): filename = os.path.join(my_path, "emd_files", "example_axis_len_1.emd") - signal = load(filename) + signal = hs.load(filename) assert signal.data.shape == (5, 1, 5) @@ -154,26 +149,26 @@ def teardown_method(self): self.tmpdir.cleanup() def test_load_with_dataset_path(self): - s = load(self.hdf5_dataset_path) + s = hs.load(self.hdf5_dataset_path) assert len(s) == len(self.dataset_path_list) for dataset_path, data_size in zip(self.dataset_path_list, self.data_size_list): - s = load(self.hdf5_dataset_path, dataset_path=dataset_path) + s = hs.load(self.hdf5_dataset_path, dataset_path=dataset_path) title = os.path.basename(os.path.dirname(dataset_path)) assert s.metadata.General.title == title assert s.data.shape == data_size[::-1] def test_load_with_dataset_path_several(self): dataset_path = self.dataset_path_list[0:2] - s = load(self.hdf5_dataset_path, dataset_path=dataset_path) + s = hs.load(self.hdf5_dataset_path, dataset_path=dataset_path) assert len(s) == len(dataset_path) assert s[0].metadata.General.title in dataset_path[0] assert s[1].metadata.General.title in dataset_path[1] def test_wrong_dataset_path(self): with pytest.raises(IOError): - load(self.hdf5_dataset_path, dataset_path="a_wrong_name") + hs.load(self.hdf5_dataset_path, dataset_path="a_wrong_name") with pytest.raises(IOError): - load( + hs.load( self.hdf5_dataset_path, dataset_path=[self.dataset_path_list[0], "a_wrong_name"], ) @@ -181,11 +176,11 @@ def test_wrong_dataset_path(self): def test_deprecated_dataset_name(self): with pytest.warns(UserWarning): dataset_name = os.path.dirname(self.dataset_path_list[0]) - load(self.hdf5_dataset_path, dataset_name=dataset_name) + hs.load(self.hdf5_dataset_path, dataset_name=dataset_name) def test_minimal_save(): - signal = Signal1D([0, 1]) + signal = hs.signals.Signal1D([0, 1]) with tempfile.TemporaryDirectory() as tmp: signal.save(os.path.join(tmp, "testfile.emd")) @@ -218,7 +213,7 @@ def teardown_method(self): self.tmpdir.cleanup() def test_load_file(self): - s = load(self.hdf5_dataset_path) + s = hs.load(self.hdf5_dataset_path) assert len(s) == len(self.group_path_list) for _s, path in zip(s, self.group_path_list): assert _s.metadata.General.title in path @@ -227,7 +222,7 @@ def test_load_file(self): class TestCaseSaveAndRead: @pytest.mark.parametrize("lazy", (True, False)) def test_save_and_read(self, lazy): - signal_ref = BaseSignal(data_save) + signal_ref = hs.signals.BaseSignal(data_save) signal_ref.metadata.General.title = test_title signal_ref.axes_manager[0].name = "x" signal_ref.axes_manager[1].name = "y" @@ -249,7 +244,9 @@ def test_save_and_read(self, lazy): signal_ref.save( os.path.join(my_path, "emd_files", "example_temp.emd"), overwrite=True ) - signal = load(os.path.join(my_path, "emd_files", "example_temp.emd"), lazy=lazy) + signal = hs.load( + os.path.join(my_path, "emd_files", "example_temp.emd"), lazy=lazy + ) if lazy: signal.compute(close_file=True) om = signal.original_metadata @@ -272,26 +269,26 @@ def test_save_and_read(self, lazy): np.testing.assert_equal(om.sample.as_dictionary(), sample) np.testing.assert_equal(om.comments.as_dictionary(), comments) - assert isinstance(signal, BaseSignal) + assert isinstance(signal, hs.signals.BaseSignal) def teardown_method(self, method): os.remove(os.path.join(my_path, "emd_files", "example_temp.emd")) def test_chunking_saving_lazy(): - s = Signal2D(da.zeros((50, 100, 100))).as_lazy() + s = hs.signals.Signal2D(da.zeros((50, 100, 100))).as_lazy() s.data = s.data.rechunk([50, 25, 25]) with tempfile.TemporaryDirectory() as tmp: filename = os.path.join(tmp, "test_chunking_saving_lazy.emd") filename2 = os.path.join(tmp, "test_chunking_saving_lazy_chunks_True.emd") filename3 = os.path.join(tmp, "test_chunking_saving_lazy_chunks_specify.emd") s.save(filename) - s1 = load(filename, lazy=True) + s1 = hs.load(filename, lazy=True) assert s.data.chunks == s1.data.chunks # with chunks=True, use h5py chunking s.save(filename2, chunks=True) - s2 = load(filename2, lazy=True) + s2 = hs.load(filename2, lazy=True) assert tuple([c[0] for c in s2.data.chunks]) == (13, 25, 13) s1.close_file() s2.close_file() @@ -299,7 +296,7 @@ def test_chunking_saving_lazy(): # Specify chunks chunks = (50, 20, 20) s.save(filename3, chunks=chunks) - s3 = load(filename3, lazy=True) + s3 = hs.load(filename3, lazy=True) assert tuple([c[0] for c in s3.data.chunks]) == chunks @@ -330,6 +327,7 @@ def teardown_class(cls): @pytest.mark.parametrize("lazy", (True, False)) def test_fei_emd_image(self, lazy): + stage = { "tilt_alpha": 0.006, "tilt_beta": 0.000, @@ -356,7 +354,7 @@ def test_fei_emd_image(self, lazy): "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.emd.api", } }, @@ -379,7 +377,9 @@ def test_fei_emd_image(self, lazy): md["General"]["date"] = date md["General"]["time"] = time - signal = load(os.path.join(self.fei_files_path, "fei_emd_image.emd"), lazy=lazy) + signal = hs.load( + os.path.join(self.fei_files_path, "fei_emd_image.emd"), lazy=lazy + ) # delete timestamp from metadata since it's runtime dependent del signal.metadata.General.FileIO.Number_0.timestamp if lazy: @@ -396,11 +396,11 @@ def test_fei_emd_image(self, lazy): np.testing.assert_allclose(signal.axes_manager[1].scale, 0.00530241, rtol=1e-5) np.testing.assert_allclose(signal.data, fei_image) assert_deep_almost_equal(signal.metadata.as_dictionary(), md) - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) @pytest.mark.parametrize("lazy", (True, False)) def test_fei_emd_spectrum(self, lazy): - signal = load( + signal = hs.load( os.path.join(self.fei_files_path, "fei_emd_spectrum.emd"), lazy=lazy ) if lazy: @@ -410,21 +410,21 @@ def test_fei_emd_spectrum(self, lazy): os.path.join(self.fei_files_path, "fei_emd_spectrum.npy") ) np.testing.assert_equal(signal.data, fei_spectrum) - assert isinstance(signal, Signal1D) + assert isinstance(signal, hs.signals.Signal1D) @pytest.mark.parametrize("lazy", (True, False)) def test_fei_emd_si(self, lazy): - signal = load(os.path.join(self.fei_files_path, "fei_emd_si.emd"), lazy=lazy) + signal = hs.load(os.path.join(self.fei_files_path, "fei_emd_si.emd"), lazy=lazy) if lazy: assert signal[1]._lazy signal[1].compute(close_file=True) fei_si = np.load(os.path.join(self.fei_files_path, "fei_emd_si.npy")) np.testing.assert_equal(signal[1].data, fei_si) - assert isinstance(signal[1], Signal1D) + assert isinstance(signal[1], hs.signals.Signal1D) @pytest.mark.parametrize("lazy", (True, False)) def test_fei_emd_si_non_square_10frames(self, lazy): - s = load( + s = hs.load( os.path.join(self.fei_files_path, "fei_SI_SuperX-HAADF_10frames_10x50.emd"), lazy=lazy, ) @@ -432,7 +432,7 @@ def test_fei_emd_si_non_square_10frames(self, lazy): if lazy: assert signal._lazy signal.compute(close_file=True) - assert isinstance(signal, EDSTEMSpectrum) + assert isinstance(signal, hs.signals.EDSTEMSpectrum) assert signal.axes_manager[0].name == "x" assert signal.axes_manager[0].size == 10 assert signal.axes_manager[0].units == "nm" @@ -450,7 +450,7 @@ def test_fei_emd_si_non_square_10frames(self, lazy): if lazy: assert signal0._lazy signal0.compute(close_file=True) - assert isinstance(signal0, Signal2D) + assert isinstance(signal0, hs.signals.Signal2D) assert signal0.axes_manager[0].name == "x" assert signal0.axes_manager[0].size == 10 assert signal0.axes_manager[0].units == "nm" @@ -459,7 +459,7 @@ def test_fei_emd_si_non_square_10frames(self, lazy): assert signal0.axes_manager[1].size == 50 assert signal0.axes_manager[1].units == "nm" - s = load( + s = hs.load( os.path.join(self.fei_files_path, "fei_SI_SuperX-HAADF_10frames_10x50.emd"), lazy=lazy, load_SI_image_stack=True, @@ -468,7 +468,7 @@ def test_fei_emd_si_non_square_10frames(self, lazy): if lazy: assert signal._lazy signal.compute(close_file=True) - assert isinstance(signal, EDSTEMSpectrum) + assert isinstance(signal, hs.signals.EDSTEMSpectrum) assert signal.axes_manager[0].name == "x" assert signal.axes_manager[0].size == 10 assert signal.axes_manager[0].units == "nm" @@ -486,7 +486,7 @@ def test_fei_emd_si_non_square_10frames(self, lazy): if lazy: assert signal0._lazy signal0.compute(close_file=True) - assert isinstance(signal0, Signal2D) + assert isinstance(signal0, hs.signals.Signal2D) assert signal0.axes_manager[0].name == "Time" assert signal0.axes_manager[0].size == 10 assert signal0.axes_manager[0].units == "s" @@ -498,7 +498,7 @@ def test_fei_emd_si_non_square_10frames(self, lazy): assert signal0.axes_manager[2].size == 50 assert signal0.axes_manager[2].units == "nm" - s = load( + s = hs.load( os.path.join(self.fei_files_path, "fei_SI_SuperX-HAADF_10frames_10x50.emd"), sum_frames=False, SI_dtype=np.uint8, @@ -509,7 +509,7 @@ def test_fei_emd_si_non_square_10frames(self, lazy): if lazy: assert signal._lazy signal.compute(close_file=True) - assert isinstance(signal, EDSTEMSpectrum) + assert isinstance(signal, hs.signals.EDSTEMSpectrum) assert signal.axes_manager.navigation_shape == (10, 50, 10) assert signal.axes_manager[0].name == "x" assert signal.axes_manager[0].size == 10 @@ -528,7 +528,7 @@ def test_fei_emd_si_non_square_10frames(self, lazy): assert signal.axes_manager[3].units == "keV" np.testing.assert_allclose(signal.axes_manager[3].scale, 1.28, atol=1e-5) - s = load( + s = hs.load( os.path.join(self.fei_files_path, "fei_SI_SuperX-HAADF_10frames_10x50.emd"), sum_frames=False, last_frame=5, @@ -540,7 +540,7 @@ def test_fei_emd_si_non_square_10frames(self, lazy): if lazy: assert signal._lazy signal.compute(close_file=True) - assert isinstance(signal, EDSTEMSpectrum) + assert isinstance(signal, hs.signals.EDSTEMSpectrum) assert signal.axes_manager.navigation_shape == (10, 50, 5) assert signal.axes_manager[0].name == "x" assert signal.axes_manager[0].size == 10 @@ -559,7 +559,7 @@ def test_fei_emd_si_non_square_10frames(self, lazy): assert signal.axes_manager[3].units == "keV" np.testing.assert_allclose(signal.axes_manager[3].scale, 1.28, atol=1e-5) - s = load( + s = hs.load( os.path.join(self.fei_files_path, "fei_SI_SuperX-HAADF_10frames_10x50.emd"), sum_frames=False, first_frame=4, @@ -571,7 +571,7 @@ def test_fei_emd_si_non_square_10frames(self, lazy): if lazy: assert signal._lazy signal.compute(close_file=True) - assert isinstance(signal, EDSTEMSpectrum) + assert isinstance(signal, hs.signals.EDSTEMSpectrum) assert signal.axes_manager.navigation_shape == (10, 50, 6) assert signal.axes_manager[0].name == "x" assert signal.axes_manager[0].size == 10 @@ -592,7 +592,7 @@ def test_fei_emd_si_non_square_10frames(self, lazy): @pytest.mark.parametrize("lazy", (True, False)) def test_fei_emd_si_non_square_20frames(self, lazy): - s = load( + s = hs.load( os.path.join(self.fei_files_path, "fei_SI_SuperX-HAADF_20frames_10x50.emd"), lazy=lazy, ) @@ -600,7 +600,7 @@ def test_fei_emd_si_non_square_20frames(self, lazy): if lazy: assert signal._lazy signal.compute(close_file=True) - assert isinstance(signal, EDSTEMSpectrum) + assert isinstance(signal, hs.signals.EDSTEMSpectrum) assert signal.axes_manager[0].name == "x" assert signal.axes_manager[0].size == 10 assert signal.axes_manager[0].units == "nm" @@ -616,7 +616,7 @@ def test_fei_emd_si_non_square_20frames(self, lazy): @pytest.mark.parametrize("lazy", (True, False)) def test_fei_emd_si_non_square_20frames_2eV(self, lazy): - s = load( + s = hs.load( os.path.join( self.fei_files_path, "fei_SI_SuperX-HAADF_20frames_10x50_2ev.emd" ), @@ -626,7 +626,7 @@ def test_fei_emd_si_non_square_20frames_2eV(self, lazy): if lazy: assert signal._lazy signal.compute(close_file=True) - assert isinstance(signal, EDSTEMSpectrum) + assert isinstance(signal, hs.signals.EDSTEMSpectrum) assert signal.axes_manager[0].name == "x" assert signal.axes_manager[0].size == 10 assert signal.axes_manager[0].units == "nm" @@ -642,7 +642,7 @@ def test_fei_emd_si_non_square_20frames_2eV(self, lazy): @pytest.mark.parametrize("lazy", (True, False)) def test_fei_emd_si_frame_range(self, lazy): - signal = load( + signal = hs.load( os.path.join(self.fei_files_path, "fei_emd_si.emd"), first_frame=2, last_frame=4, @@ -653,14 +653,14 @@ def test_fei_emd_si_frame_range(self, lazy): assert signal[1]._lazy signal[1].compute(close_file=True) np.testing.assert_equal(signal[1].data, fei_si) - assert isinstance(signal[1], Signal1D) + assert isinstance(signal[1], hs.signals.Signal1D) @pytest.mark.parametrize(["lazy", "sum_EDS_detectors"], _generate_parameters()) def test_fei_si_4detectors(self, lazy, sum_EDS_detectors): fname = os.path.join( self.fei_files_path, "fei_SI_EDS-HAADF-4detectors_2frames.emd" ) - signal = load(fname, sum_EDS_detectors=sum_EDS_detectors, lazy=lazy) + signal = hs.load(fname, sum_EDS_detectors=sum_EDS_detectors, lazy=lazy) if lazy: assert signal[1]._lazy signal[1].compute(close_file=True) @@ -671,17 +671,17 @@ def test_fei_si_4detectors(self, lazy, sum_EDS_detectors): # TODO: add parsing azimuth_angle def test_fei_emd_ceta_camera(self): - signal = load(os.path.join(self.fei_files_path, "1532 Camera Ceta.emd")) + signal = hs.load(os.path.join(self.fei_files_path, "1532 Camera Ceta.emd")) np.testing.assert_allclose(signal.data, np.zeros((64, 64))) - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) date, time = self._convert_datetime(1512055942.914275).split("T") assert signal.metadata.General.date == date assert signal.metadata.General.time == time assert signal.metadata.General.time_zone == self._get_local_time_zone() - signal = load(os.path.join(self.fei_files_path, "1854 Camera Ceta.emd")) + signal = hs.load(os.path.join(self.fei_files_path, "1854 Camera Ceta.emd")) np.testing.assert_allclose(signal.data, np.zeros((64, 64))) - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) def _convert_datetime(self, unix_time): # Since we don't know the actual time zone of where the data have been @@ -704,7 +704,7 @@ def time_loading_frame(self): for i, frame_offset in enumerate(frame_offsets): print(frame_offset + frame_number) t0 = time.time() - load( + hs.load( os.path.join(path, "large dataset.emd"), first_frame=frame_offset, last_frame=frame_offset + frame_number, @@ -719,26 +719,26 @@ def time_loading_frame(self): def test_fei_complex_loading(): - signal = load(os.path.join(my_path, "emd_files", "fei_example_complex_fft.emd")) - assert isinstance(signal, ComplexSignal2D) + signal = hs.load(os.path.join(my_path, "emd_files", "fei_example_complex_fft.emd")) + assert isinstance(signal, hs.signals.ComplexSignal2D) def test_fei_complex_loading_lazy(): - signal = load( + signal = hs.load( os.path.join(my_path, "emd_files", "fei_example_complex_fft.emd"), lazy=True ) - assert isinstance(signal, ComplexSignal2D) + assert isinstance(signal, hs.signals.ComplexSignal2D) def test_fei_no_frametime(): - signal = load(os.path.join(my_path, "emd_files", "fei_example_tem_stack.emd")) - assert isinstance(signal, Signal2D) + signal = hs.load(os.path.join(my_path, "emd_files", "fei_example_tem_stack.emd")) + assert isinstance(signal, hs.signals.Signal2D) assert signal.data.shape == (2, 3, 3) assert signal.axes_manager["Time"].scale == 0.8 def test_fei_dpc_loading(): - signals = load(os.path.join(my_path, "emd_files", "fei_example_dpc_titles.emd")) + signals = hs.load(os.path.join(my_path, "emd_files", "fei_example_dpc_titles.emd")) assert signals[0].metadata.General.title == "B-D" assert signals[1].metadata.General.title == "DPC" assert signals[2].metadata.General.title == "iDPC" @@ -748,12 +748,12 @@ def test_fei_dpc_loading(): assert signals[6].metadata.General.title == "A-C" assert signals[7].metadata.General.title == "DF4-D" assert signals[8].metadata.General.title == "Filtered iDPC" - assert isinstance(signals[0], Signal2D) - assert isinstance(signals[1], ComplexSignal2D) - assert isinstance(signals[2], Signal2D) - assert isinstance(signals[3], Signal2D) - assert isinstance(signals[4], Signal2D) - assert isinstance(signals[5], Signal2D) - assert isinstance(signals[6], Signal2D) - assert isinstance(signals[7], Signal2D) - assert isinstance(signals[8], Signal2D) + assert isinstance(signals[0], hs.signals.Signal2D) + assert isinstance(signals[1], hs.signals.ComplexSignal2D) + assert isinstance(signals[2], hs.signals.Signal2D) + assert isinstance(signals[3], hs.signals.Signal2D) + assert isinstance(signals[4], hs.signals.Signal2D) + assert isinstance(signals[5], hs.signals.Signal2D) + assert isinstance(signals[6], hs.signals.Signal2D) + assert isinstance(signals[7], hs.signals.Signal2D) + assert isinstance(signals[8], hs.signals.Signal2D) diff --git a/rsciio/tests/test_emd_prismatic.py b/rsciio/tests/test_emd_prismatic.py index 26ba46711..636f1c1a5 100644 --- a/rsciio/tests/test_emd_prismatic.py +++ b/rsciio/tests/test_emd_prismatic.py @@ -20,9 +20,11 @@ import numpy as np import pytest + +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + import traits.api as t -import hyperspy.api as hs FILES_PATH = os.path.join(os.path.dirname(__file__), "emd_files") diff --git a/rsciio/tests/test_empad.py b/rsciio/tests/test_empad.py index 0583f2aa3..09f59a658 100644 --- a/rsciio/tests/test_empad.py +++ b/rsciio/tests/test_empad.py @@ -20,9 +20,11 @@ import numpy as np import pytest + +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + import traits.api as t -import hyperspy.api as hs from rsciio.empad.api import _parse_xml diff --git a/rsciio/tests/test_fei.py b/rsciio/tests/test_fei.py index d369b4d99..27014f806 100644 --- a/rsciio/tests/test_fei.py +++ b/rsciio/tests/test_fei.py @@ -20,9 +20,11 @@ import numpy as np import pytest + +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + import traits.api as t -from hyperspy.io import load from rsciio.fei.api import load_ser_file @@ -37,15 +39,15 @@ def setup_method(self, method): def test_load_emi_old_new_format(self): # TIA old format fname0 = os.path.join(self.dirpathold, "64x64_TEM_images_acquire.emi") - load(fname0) + hs.load(fname0) # TIA new format fname1 = os.path.join(self.dirpathnew, "128x128_TEM_acquire-sum1.emi") - load(fname1) + hs.load(fname1) def test_load_image_content(self): # TEM image of the beam stop fname0 = os.path.join(self.dirpathold, "64x64_TEM_images_acquire.emi") - s0 = load(fname0) + s0 = hs.load(fname0) data = np.load(fname0.replace("emi", "npy")) np.testing.assert_array_equal(s0.data, data) @@ -61,14 +63,14 @@ def test_load_ser_reader_old_new_format(self): def test_load_no_acquire_date(self, caplog): fname = os.path.join(self.dirpathold, "no_AcquireDate.emi") - s = load(fname) + s = hs.load(fname) assert not hasattr(s.metadata.General, "date") assert not hasattr(s.metadata.General, "time") assert "AcquireDate not found in metadata" in caplog.text def test_load_more_ser_than_metadata(self, caplog): fname = os.path.join(self.dirpathold, "more_ser_then_emi_metadata.emi") - s0, s1 = load(fname, only_valid_data=True) + s0, s1 = hs.load(fname, only_valid_data=True) assert hasattr(s0.original_metadata, "ObjectInfo") assert not hasattr(s1.original_metadata, "ObjectInfo") assert ( @@ -91,7 +93,7 @@ def prepare_non_zero_float(self): def test_load_non_zero_float(self, prepare_non_zero_float, caplog): fname = os.path.join(self.dirpathold, "non_float_meta_value_zeroed.emi") - s = load(fname) + s = hs.load(fname) assert ( s.original_metadata.ObjectInfo.ExperimentalDescription.as_dictionary()[ "OBJ Aperture_um" @@ -102,7 +104,7 @@ def test_load_non_zero_float(self, prepare_non_zero_float, caplog): def test_load_diffraction_point(self): fname0 = os.path.join(self.dirpathold, "64x64_diffraction_acquire.emi") - s0 = load(fname0) + s0 = hs.load(fname0) assert s0.data.shape == (64, 64) assert s0.axes_manager.signal_dimension == 2 assert s0.metadata.Acquisition_instrument.TEM.acquisition_mode == "TEM" @@ -117,7 +119,7 @@ def test_load_diffraction_line_scan(self): fname0 = os.path.join( self.dirpathnew, "16x16-line_profile_horizontal_5x128x128_EDS.emi" ) - s0 = load(fname0) + s0 = hs.load(fname0) # s0[0] contains EDS assert s0[0].data.shape == (5, 4000) assert s0[0].axes_manager.signal_dimension == 1 @@ -147,7 +149,7 @@ def test_load_diffraction_area_scan(self): fname0 = os.path.join( self.dirpathnew, "16x16-diffraction_imagel_5x5x256x256_EDS.emi" ) - s0 = load(fname0) + s0 = hs.load(fname0) # s0[0] contains EDS assert s0[0].data.shape == (5, 5, 4000) assert s0[0].axes_manager.signal_dimension == 1 @@ -181,7 +183,7 @@ def test_load_diffraction_area_scan(self): def test_load_spectrum_point(self): fname0 = os.path.join(self.dirpathold, "16x16-point_spectrum-1x1024.emi") - s0 = load(fname0) + s0 = hs.load(fname0) assert s0.data.shape == (1, 1024) assert s0.axes_manager.signal_dimension == 1 assert s0.metadata.Acquisition_instrument.TEM.acquisition_mode == "STEM" @@ -200,7 +202,7 @@ def test_load_spectrum_point(self): assert s0.axes_manager[1].name == "Energy" fname1 = os.path.join(self.dirpathold, "16x16-2_point-spectra-2x1024.emi") - s1 = load(fname1) + s1 = hs.load(fname1) assert s1.data.shape == (2, 1024) assert s1.axes_manager.signal_dimension == 1 assert s1.metadata.Acquisition_instrument.TEM.acquisition_mode == "STEM" @@ -212,7 +214,7 @@ def test_load_spectrum_line_scan(self): fname0 = os.path.join( self.dirpathold, "16x16-line_profile_horizontal_10x1024.emi" ) - s0 = load(fname0) + s0 = hs.load(fname0) assert s0.data.shape == (10, 1024) assert s0.axes_manager.signal_dimension == 1 assert s0.metadata.Acquisition_instrument.TEM.acquisition_mode == "STEM" @@ -226,7 +228,7 @@ def test_load_spectrum_line_scan(self): fname1 = os.path.join( self.dirpathold, "16x16-line_profile_diagonal_10x1024.emi" ) - s1 = load(fname1) + s1 = hs.load(fname1) assert s1.data.shape == (10, 1024) assert s1.axes_manager.signal_dimension == 1 assert s1.metadata.Acquisition_instrument.TEM.acquisition_mode == "STEM" @@ -238,7 +240,7 @@ def test_load_spectrum_line_scan(self): def test_load_spectrum_area_scan(self): fname0 = os.path.join(self.dirpathold, "16x16-spectrum_image-5x5x1024.emi") - s0 = load(fname0) + s0 = hs.load(fname0) assert s0.data.shape == (5, 5, 1024) assert s0.axes_manager.signal_dimension == 1 assert s0.metadata.Acquisition_instrument.TEM.acquisition_mode == "STEM" @@ -256,7 +258,7 @@ def test_load_spectrum_area_scan_not_square(self): fname0 = os.path.join( self.dirpathnew, "16x16-spectrum_image_5x5x4000-not_square.emi" ) - s0 = load(fname0) + s0 = hs.load(fname0) assert s0.data.shape == (5, 5, 4000) assert s0.axes_manager.signal_dimension == 1 assert s0.metadata.Acquisition_instrument.TEM.acquisition_mode == "STEM" @@ -269,7 +271,7 @@ def test_load_spectrum_area_scan_not_square(self): def test_load_search(self): fname0 = os.path.join(self.dirpathnew, "128x128-TEM_search.emi") - s0 = load(fname0) + s0 = hs.load(fname0) assert s0.data.shape == (128, 128) np.testing.assert_allclose(s0.axes_manager[0].scale, 5.26121, rtol=1e-5) assert s0.axes_manager[0].units == "nm" @@ -277,7 +279,7 @@ def test_load_search(self): assert s0.axes_manager[1].units == "nm" fname1 = os.path.join(self.dirpathold, "16x16_STEM_BF_DF_search.emi") - s1 = load(fname1) + s1 = hs.load(fname1) assert len(s1) == 2 for s in s1: assert s.data.shape == (16, 16) @@ -289,7 +291,7 @@ def test_load_search(self): def test_load_stack_image_preview(self): fname0 = os.path.join(self.dirpathold, "64x64x5_TEM_preview.emi") - s0 = load(fname0) + s0 = hs.load(fname0) assert s0.data.shape == (5, 64, 64) assert s0.axes_manager.signal_dimension == 2 assert s0.metadata.Acquisition_instrument.TEM.acquisition_mode == "TEM" @@ -306,7 +308,7 @@ def test_load_stack_image_preview(self): assert s0.axes_manager[2].name == "y" fname2 = os.path.join(self.dirpathnew, "128x128x5-diffraction_preview.emi") - s2 = load(fname2) + s2 = hs.load(fname2) assert s2.data.shape == (5, 128, 128) np.testing.assert_allclose(s2.axes_manager[1].scale, 0.042464, rtol=1e-5) assert s0.axes_manager[0].units is t.Undefined @@ -315,7 +317,7 @@ def test_load_stack_image_preview(self): assert s2.axes_manager[2].units == "1 / nm" fname1 = os.path.join(self.dirpathold, "16x16x5_STEM_BF_DF_preview.emi") - s1 = load(fname1) + s1 = hs.load(fname1) assert len(s1) == 2 for s in s1: assert s.data.shape == (5, 16, 16) @@ -326,7 +328,7 @@ def test_load_stack_image_preview(self): def test_load_acquire(self): fname0 = os.path.join(self.dirpathold, "64x64_TEM_images_acquire.emi") - s0 = load(fname0) + s0 = hs.load(fname0) assert s0.axes_manager.signal_dimension == 2 assert s0.metadata.Acquisition_instrument.TEM.acquisition_mode == "TEM" np.testing.assert_allclose(s0.axes_manager[0].scale, 6.281833, rtol=1e-5) @@ -337,7 +339,7 @@ def test_load_acquire(self): assert s0.axes_manager[1].name == "y" fname1 = os.path.join(self.dirpathold, "16x16_STEM_BF_DF_acquire.emi") - s1 = load(fname1) + s1 = hs.load(fname1) assert len(s1) == 2 for s in s1: assert s.data.shape == (16, 16) @@ -352,7 +354,7 @@ def test_load_acquire(self): @pytest.mark.parametrize("only_valid_data", (True, False)) def test_load_TotalNumberElements_ne_ValidNumberElements(self, only_valid_data): fname0 = os.path.join(self.dirpathold, "X - Au NP EELS_2.ser") - s0 = load(fname0, only_valid_data=only_valid_data) + s0 = hs.load(fname0, only_valid_data=only_valid_data) nav_shape = () if only_valid_data else (2,) assert s0.data.shape == nav_shape + (2048,) assert len(s0.axes_manager.navigation_axes) == len(nav_shape) @@ -360,7 +362,7 @@ def test_load_TotalNumberElements_ne_ValidNumberElements(self, only_valid_data): np.testing.assert_allclose(s0.axes_manager[-1].scale, 0.2, rtol=1e-5) fname1 = os.path.join(self.dirpathold, "03_Scanning Preview.emi") - s1 = load(fname1, only_valid_data=only_valid_data) + s1 = hs.load(fname1, only_valid_data=only_valid_data) nav_shape = (5,) if only_valid_data else (200,) assert s1.data.shape == nav_shape + (128, 128) nav_axes = s1.axes_manager.navigation_axes @@ -373,22 +375,22 @@ def test_load_TotalNumberElements_ne_ValidNumberElements(self, only_valid_data): def test_read_STEM_TEM_mode(self): # TEM image fname0 = os.path.join(self.dirpathold, "64x64_TEM_images_acquire.emi") - s0 = load(fname0) + s0 = hs.load(fname0) assert s0.metadata.Acquisition_instrument.TEM.acquisition_mode == "TEM" # TEM diffraction fname1 = os.path.join(self.dirpathold, "64x64_diffraction_acquire.emi") - s1 = load(fname1) + s1 = hs.load(fname1) assert s1.metadata.Acquisition_instrument.TEM.acquisition_mode == "TEM" fname2 = os.path.join(self.dirpathold, "16x16_STEM_BF_DF_acquire.emi") # STEM diffraction - s2 = load(fname2) + s2 = hs.load(fname2) assert s2[0].metadata.Acquisition_instrument.TEM.acquisition_mode == "STEM" assert s2[1].metadata.Acquisition_instrument.TEM.acquisition_mode == "STEM" def test_load_units_scale(self): # TEM image fname0 = os.path.join(self.dirpathold, "64x64_TEM_images_acquire.emi") - s0 = load(fname0) + s0 = hs.load(fname0) np.testing.assert_allclose(s0.axes_manager[0].scale, 6.28183, rtol=1e-5) assert s0.axes_manager[0].units == "nm" np.testing.assert_allclose( @@ -396,7 +398,7 @@ def test_load_units_scale(self): ) # TEM diffraction fname1 = os.path.join(self.dirpathold, "64x64_diffraction_acquire.emi") - s1 = load(fname1) + s1 = hs.load(fname1) np.testing.assert_allclose(s1.axes_manager[0].scale, 0.101571, rtol=1e-5) assert s1.axes_manager[0].units == "1 / nm" np.testing.assert_allclose( @@ -404,7 +406,7 @@ def test_load_units_scale(self): ) # STEM diffraction fname2 = os.path.join(self.dirpathold, "16x16_STEM_BF_DF_acquire.emi") - s2 = load(fname2) + s2 = hs.load(fname2) assert s2[0].axes_manager[0].units == "nm" np.testing.assert_allclose(s2[0].axes_manager[0].scale, 21.5100, rtol=1e-5) np.testing.assert_allclose( @@ -439,7 +441,7 @@ def test_load_multisignal_stack(self, stack_metadata): fname0 = os.path.join( self.dirpathnew, "16x16-line_profile_horizontal_5x128x128_EDS.emi" ) - s = load([fname0, fname0], stack=True, stack_metadata=stack_metadata) + s = hs.load([fname0, fname0], stack=True, stack_metadata=stack_metadata) assert s[0].axes_manager.navigation_shape == (5, 2) assert s[0].axes_manager.signal_shape == (4000,) assert s[1].axes_manager.navigation_shape == (5, 2) @@ -456,25 +458,25 @@ def test_load_multisignal_stack_mismatch(self): self.dirpathnew, "16x16-diffraction_imagel_5x5x256x256_EDS_copy.emi" ) with pytest.raises(ValueError) as cm: - load([fname0, fname1], stack=True) + hs.load([fname0, fname1], stack=True) cm.match("The number of sub-signals per file does not match*") - load([fname0, fname1]) + hs.load([fname0, fname1]) def test_date_time(self): fname0 = os.path.join(self.dirpathold, "64x64_TEM_images_acquire.emi") - s = load(fname0) + s = hs.load(fname0) assert s.metadata.General.date == "2016-02-21" assert s.metadata.General.time == "17:50:18" fname1 = os.path.join( self.dirpathold, "16x16-line_profile_horizontal_10x1024.emi" ) - s = load(fname1) + s = hs.load(fname1) assert s.metadata.General.date == "2016-02-22" assert s.metadata.General.time == "11:50:36" def test_metadata_TEM(self): fname0 = os.path.join(self.dirpathold, "64x64_TEM_images_acquire.emi") - s = load(fname0) + s = hs.load(fname0) assert s.metadata.Acquisition_instrument.TEM.beam_energy == 200.0 assert s.metadata.Acquisition_instrument.TEM.magnification == 19500.0 assert ( @@ -487,7 +489,7 @@ def test_metadata_TEM(self): def test_metadata_STEM(self): fname0 = os.path.join(self.dirpathold, "16x16_STEM_BF_DF_acquire.emi") - s = load(fname0)[0] + s = hs.load(fname0)[0] assert s.metadata.Acquisition_instrument.TEM.beam_energy == 200.0 assert s.metadata.Acquisition_instrument.TEM.camera_length == 40.0 assert s.metadata.Acquisition_instrument.TEM.magnification == 10000.0 @@ -513,7 +515,7 @@ def test_metadata_STEM(self): def test_metadata_diffraction(self): fname0 = os.path.join(self.dirpathold, "64x64_diffraction_acquire.emi") - s = load(fname0) + s = hs.load(fname0) assert s.metadata.Acquisition_instrument.TEM.beam_energy == 200.0 assert s.metadata.Acquisition_instrument.TEM.camera_length == 490.0 assert ( diff --git a/rsciio/tests/test_hdf5.py b/rsciio/tests/test_hdf5.py index cfb9e06bf..ac77e9b1b 100644 --- a/rsciio/tests/test_hdf5.py +++ b/rsciio/tests/test_hdf5.py @@ -26,18 +26,13 @@ import numpy as np import pytest -from hyperspy import __version__ as hs_version -from hyperspy.io import load +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + from hyperspy.axes import DataAxis, UniformDataAxis, FunctionalDataAxis, AxesManager -from hyperspy.signal import BaseSignal -from hyperspy._signals.signal1d import Signal1D -from hyperspy._signals.signal2d import Signal2D -from hyperspy.datasets.example_signals import EDS_TEM_Spectrum from hyperspy.decorators import lazifyTestClass from hyperspy.misc.test_utils import assert_deep_almost_equal from hyperspy.misc.test_utils import sanitize_dict as san_dict -from hyperspy.roi import Point2DROI -from hyperspy.utils import markers + from rsciio._hierarchical import get_signal_chunks from rsciio.utils.tools import get_file_handle @@ -145,7 +140,7 @@ def test_original_metadata(self): class TestExample1_12(Example1): def setup_method(self, method): - self.s = load(my_path / "hdf5_files" / "example1_v1.2.hdf5", reader="HSPY") + self.s = hs.load(my_path / "hdf5_files" / "example1_v1.2.hdf5", reader="HSPY") def test_date(self): assert self.s.metadata.General.date == "1991-10-01" @@ -156,17 +151,17 @@ def test_time(self): class TestExample1_10(Example1): def setup_method(self, method): - self.s = load(my_path / "hdf5_files" / "example1_v1.0.hdf5", reader="HSPY") + self.s = hs.load(my_path / "hdf5_files" / "example1_v1.0.hdf5", reader="HSPY") class TestExample1_11(Example1): def setup_method(self, method): - self.s = load(my_path / "hdf5_files" / "example1_v1.1.hdf5", reader="HSPY") + self.s = hs.load(my_path / "hdf5_files" / "example1_v1.1.hdf5", reader="HSPY") class TestLoadingNewSavedMetadata: def setup_method(self, method): - self.s = load(my_path / "hdf5_files" / "with_lists_etc.hdf5", reader="HSPY") + self.s = hs.load(my_path / "hdf5_files" / "with_lists_etc.hdf5", reader="HSPY") def test_signal_inside(self): np.testing.assert_array_almost_equal( @@ -199,7 +194,7 @@ def test_binary_string(self): class TestSavingMetadataContainers: def setup_method(self, method): - self.s = BaseSignal([0.1]) + self.s = hs.signals.BaseSignal([0.1]) @zspy_marker def test_save_unicode(self, tmp_path, file): @@ -207,7 +202,7 @@ def test_save_unicode(self, tmp_path, file): s.metadata.set_item("test", ["a", "b", "\u6f22\u5b57"]) fname = tmp_path / file s.save(fname) - l = load(fname) + l = hs.load(fname) assert isinstance(l.metadata.test[0], str) assert isinstance(l.metadata.test[1], str) assert isinstance(l.metadata.test[2], str) @@ -231,7 +226,7 @@ def test_numpy_only_inner_lists(self, tmp_path, file): s.metadata.set_item("test", [[1.0, 2], ("3", 4)]) fname = tmp_path / file s.save(fname) - l = load(fname) + l = hs.load(fname) assert isinstance(l.metadata.test, list) assert isinstance(l.metadata.test[0], list) assert isinstance(l.metadata.test[1], tuple) @@ -243,7 +238,7 @@ def test_numpy_general_type(self, tmp_path, file): s.metadata.set_item("test", np.array([[1.0, 2], ["3", 4]])) fname = tmp_path / file s.save(fname) - l = load(fname) + l = hs.load(fname) np.testing.assert_array_equal(l.metadata.test, s.metadata.test) @pytest.mark.xfail(sys.platform == "win32", reason="randomly fails in win32") @@ -253,7 +248,7 @@ def test_list_general_type(self, tmp_path, file): s.metadata.set_item("test", [[1.0, 2], ["3", 4]]) fname = tmp_path / file s.save(fname) - l = load(fname) + l = hs.load(fname) assert isinstance(l.metadata.test[0][0], float) assert isinstance(l.metadata.test[0][1], float) assert isinstance(l.metadata.test[1][0], str) @@ -263,22 +258,22 @@ def test_list_general_type(self, tmp_path, file): @zspy_marker def test_general_type_not_working(self, tmp_path, file): s = self.s - s.metadata.set_item("test", (BaseSignal([1]), 0.1, "test_string")) + s.metadata.set_item("test", (hs.signals.BaseSignal([1]), 0.1, "test_string")) fname = tmp_path / file s.save(fname) - l = load(fname) + l = hs.load(fname) assert isinstance(l.metadata.test, tuple) - assert isinstance(l.metadata.test[0], Signal1D) + assert isinstance(l.metadata.test[0], hs.signals.Signal1D) assert isinstance(l.metadata.test[1], float) assert isinstance(l.metadata.test[2], str) @zspy_marker def test_unsupported_type(self, tmp_path, file): s = self.s - s.metadata.set_item("test", Point2DROI(1, 2)) + s.metadata.set_item("test", hs.roi.Point2DROI(1, 2)) fname = tmp_path / file s.save(fname) - l = load(fname) + l = hs.load(fname) assert "test" not in l.metadata @zspy_marker @@ -289,7 +284,7 @@ def test_date_time(self, tmp_path, file): s.metadata.General.time = time fname = tmp_path / file s.save(fname) - l = load(fname) + l = hs.load(fname) assert l.metadata.General.date == date assert l.metadata.General.time == time @@ -304,7 +299,7 @@ def test_general_metadata(self, tmp_path, file): s.metadata.General.doi = doi fname = tmp_path / file s.save(fname) - l = load(fname) + l = hs.load(fname) assert l.metadata.General.notes == notes assert l.metadata.General.authors == authors assert l.metadata.General.doi == doi @@ -316,7 +311,7 @@ def test_quantity(self, tmp_path, file): s.metadata.Signal.quantity = quantity fname = tmp_path / file s.save(fname) - l = load(fname) + l = hs.load(fname) assert l.metadata.Signal.quantity == quantity @zspy_marker @@ -325,7 +320,7 @@ def test_save_axes_manager(self, tmp_path, file): s.metadata.set_item("test", s.axes_manager) fname = tmp_path / file s.save(fname) - l = load(fname) + l = hs.load(fname) # strange becuase you need the encoding... assert isinstance(l.metadata.test, AxesManager) @@ -335,7 +330,7 @@ def test_title(self, tmp_path, file): fname = tmp_path / file s.metadata.General.title = "__unnamed__" s.save(fname) - l = load(fname) + l = hs.load(fname) assert l.metadata.General.title == "" @zspy_marker @@ -344,7 +339,7 @@ def test_save_empty_tuple(self, tmp_path, file): s.metadata.set_item("test", ()) fname = tmp_path / file s.save(fname) - l = load(fname) + l = hs.load(fname) # strange becuase you need the encoding... assert l.metadata.test == s.metadata.test @@ -355,12 +350,12 @@ def test_save_bytes(self, tmp_path, file): s.metadata.set_item("test", byte_message) fname = tmp_path / file s.save(fname) - l = load(fname) + l = hs.load(fname) assert l.metadata.test == s.metadata.test.decode() def test_metadata_binned_deprecate(self): with pytest.warns(UserWarning, match="Loading old file"): - s = load(my_path / "hdf5_files" / "example2_v2.2.hspy") + s = hs.load(my_path / "hdf5_files" / "example2_v2.2.hspy") assert s.metadata.has_item("Signal.binned") == False assert s.axes_manager[-1].is_binned == False @@ -386,7 +381,7 @@ def test_metadata_update_to_v3_1(self): "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.hspy.api", } }, @@ -407,20 +402,20 @@ def test_metadata_update_to_v3_1(self): } }, } - s = load(my_path / "hdf5_files" / "example2_v3.1.hspy") + s = hs.load(my_path / "hdf5_files" / "example2_v3.1.hspy") # delete timestamp from metadata since it's runtime dependent del s.metadata.General.FileIO.Number_0.timestamp assert_deep_almost_equal(s.metadata.as_dictionary(), md) def test_none_metadata(): - s = load(my_path / "hdf5_files" / "none_metadata.hdf5", reader="HSPY") + s = hs.load(my_path / "hdf5_files" / "none_metadata.hdf5", reader="HSPY") assert s.metadata.should_be_None is None def test_rgba16(): print(my_path) - s = load(my_path / "hdf5_files" / "test_rgba16.hdf5", reader="HSPY") + s = hs.load(my_path / "hdf5_files" / "test_rgba16.hdf5", reader="HSPY") data = np.load(my_path / "npz_files" / "test_rgba16.npz")["a"] assert (s.data == data).all() @@ -434,7 +429,7 @@ def test_non_valid_hspy(tmp_path, caplog): with pytest.raises(IOError): with caplog.at_level(logging.ERROR): - _ = load(filename) + _ = hs.load(filename) @zspy_marker @@ -443,11 +438,11 @@ def test_nonuniformaxis(tmp_path, file, lazy): fname = tmp_path / file data = np.arange(10) axis = DataAxis(axis=1 / np.arange(1, data.size + 1), navigate=False) - s = Signal1D(data, axes=(axis.get_axis_dictionary(),)) + s = hs.signals.Signal1D(data, axes=(axis.get_axis_dictionary(),)) if lazy: s = s.as_lazy() s.save(fname, overwrite=True) - s2 = load(fname) + s2 = hs.load(fname) np.testing.assert_array_almost_equal( s.axes_manager[0].axis, s2.axes_manager[0].axis ) @@ -463,12 +458,12 @@ def test_nonuniformFDA(tmp_path, file, lazy): data = np.arange(10) x0 = UniformDataAxis(size=data.size, offset=1) axis = FunctionalDataAxis(expression="1/x", x=x0, navigate=False) - s = Signal1D(data, axes=(axis.get_axis_dictionary(),)) + s = hs.signals.Signal1D(data, axes=(axis.get_axis_dictionary(),)) if lazy: s = s.as_lazy() print(axis.get_axis_dictionary()) s.save(fname, overwrite=True) - s2 = load(fname) + s2 = hs.load(fname) np.testing.assert_array_almost_equal( s.axes_manager[0].axis, s2.axes_manager[0].axis ) @@ -478,7 +473,7 @@ def test_nonuniformFDA(tmp_path, file, lazy): def test_lazy_loading(tmp_path): - s = BaseSignal(np.empty((5, 5, 5))) + s = hs.signals.BaseSignal(np.empty((5, 5, 5))) fname = tmp_path / "tmp.hdf5" s.save(fname, overwrite=True, file_format="HSPY") shape = (10000, 10000, 100) @@ -489,7 +484,7 @@ def test_lazy_loading(tmp_path): s.create_dataset("data", shape=shape, dtype="float64", chunks=True) f.close() - s = load(fname, lazy=True, reader="HSPY") + s = hs.load(fname, lazy=True, reader="HSPY") assert shape == s.data.shape assert isinstance(s.data, da.Array) assert s._lazy @@ -498,7 +493,9 @@ def test_lazy_loading(tmp_path): def test_passing_compression_opts_saving(tmp_path): filename = tmp_path / "testfile.hdf5" - BaseSignal([1, 2, 3]).save(filename, compression_opts=8, file_format="HSPY") + hs.signals.BaseSignal([1, 2, 3]).save( + filename, compression_opts=8, file_format="HSPY" + ) f = h5py.File(filename, mode="r+") d = f["Experiments/__unnamed__/data"] @@ -510,12 +507,12 @@ def test_passing_compression_opts_saving(tmp_path): @zspy_marker def test_axes_configuration(tmp_path, file): fname = tmp_path / file - s = BaseSignal(np.zeros((2, 2, 2, 2, 2))) + s = hs.signals.BaseSignal(np.zeros((2, 2, 2, 2, 2))) s.axes_manager.signal_axes[0].navigate = True s.axes_manager.signal_axes[0].navigate = True s.save(fname, overwrite=True) - s = load(fname) + s = hs.load(fname) assert s.axes_manager.navigation_axes[0].index_in_array == 4 assert s.axes_manager.navigation_axes[1].index_in_array == 3 assert s.axes_manager.signal_dimension == 3 @@ -524,25 +521,25 @@ def test_axes_configuration(tmp_path, file): @zspy_marker def test_axes_configuration_binning(tmp_path, file): fname = tmp_path / file - s = BaseSignal(np.zeros((2, 2, 2))) + s = hs.signals.BaseSignal(np.zeros((2, 2, 2))) s.axes_manager.signal_axes[-1].is_binned = True s.save(fname) - s = load(fname) + s = hs.load(fname) assert s.axes_manager.signal_axes[-1].is_binned @lazifyTestClass class Test_permanent_markers_io: def setup_method(self, method): - s = Signal2D(np.arange(100).reshape(10, 10)) + s = hs.signals.Signal2D(np.arange(100).reshape(10, 10)) self.s = s @zspy_marker def test_save_permanent_marker(self, tmp_path, file): filename = tmp_path / file s = self.s - m = markers.point(x=5, y=5) + m = hs.markers.point(x=5, y=5) s.add_marker(m, permanent=True) s.save(filename) @@ -550,12 +547,12 @@ def test_save_permanent_marker(self, tmp_path, file): def test_save_load_empty_metadata_markers(self, tmp_path, file): filename = tmp_path / file s = self.s - m = markers.point(x=5, y=5) + m = hs.markers.point(x=5, y=5) m.name = "test" s.add_marker(m, permanent=True) del s.metadata.Markers.test s.save(filename) - s1 = load(filename) + s1 = hs.load(filename) assert len(s1.metadata.Markers) == 0 @zspy_marker @@ -566,11 +563,11 @@ def test_save_load_permanent_marker(self, tmp_path, file): color = "red" size = 10 name = "testname" - m = markers.point(x=x, y=y, color=color, size=size) + m = hs.markers.point(x=x, y=y, color=color, size=size) m.name = name s.add_marker(m, permanent=True) s.save(filename) - s1 = load(filename) + s1 = hs.load(filename) assert s1.metadata.Markers.has_item(name) m1 = s1.metadata.Markers.get_item(name) assert m1.get_data_position("x1") == x @@ -585,19 +582,19 @@ def test_save_load_permanent_marker_all_types(self, tmp_path, file): s = self.s x1, y1, x2, y2 = 5, 2, 1, 8 m0_list = [ - markers.point(x=x1, y=y1), - markers.horizontal_line(y=y1), - markers.horizontal_line_segment(x1=x1, x2=x2, y=y1), - markers.line_segment(x1=x1, x2=x2, y1=y1, y2=y2), - markers.rectangle(x1=x1, x2=x2, y1=y1, y2=y2), - markers.text(x=x1, y=y1, text="test"), - markers.vertical_line(x=x1), - markers.vertical_line_segment(x=x1, y1=y1, y2=y2), + hs.markers.point(x=x1, y=y1), + hs.markers.horizontal_line(y=y1), + hs.markers.horizontal_line_segment(x1=x1, x2=x2, y=y1), + hs.markers.line_segment(x1=x1, x2=x2, y1=y1, y2=y2), + hs.markers.rectangle(x1=x1, x2=x2, y1=y1, y2=y2), + hs.markers.text(x=x1, y=y1, text="test"), + hs.markers.vertical_line(x=x1), + hs.markers.vertical_line_segment(x=x1, y1=y1, y2=y2), ] for m in m0_list: s.add_marker(m, permanent=True) s.save(filename) - s1 = load(filename) + s1 = hs.load(filename) markers_dict = s1.metadata.Markers m0_dict_list = [] m1_dict_list = [] @@ -618,11 +615,11 @@ def test_save_load_horizontal_line_marker(self, tmp_path, file): color = "blue" linewidth = 2.5 name = "horizontal_line_test" - m = markers.horizontal_line(y=y, color=color, linewidth=linewidth) + m = hs.markers.horizontal_line(y=y, color=color, linewidth=linewidth) m.name = name s.add_marker(m, permanent=True) s.save(filename) - s1 = load(filename) + s1 = hs.load(filename) m1 = s1.metadata.Markers.get_item(name) assert san_dict(m1._to_dictionary()) == san_dict(m._to_dictionary()) @@ -634,13 +631,13 @@ def test_save_load_horizontal_line_segment_marker(self, tmp_path, file): color = "red" linewidth = 1.2 name = "horizontal_line_segment_test" - m = markers.horizontal_line_segment( + m = hs.markers.horizontal_line_segment( x1=x1, x2=x2, y=y, color=color, linewidth=linewidth ) m.name = name s.add_marker(m, permanent=True) s.save(filename) - s1 = load(filename) + s1 = hs.load(filename) m1 = s1.metadata.Markers.get_item(name) assert san_dict(m1._to_dictionary()) == san_dict(m._to_dictionary()) @@ -652,11 +649,11 @@ def test_save_load_vertical_line_marker(self, tmp_path, file): color = "black" linewidth = 3.5 name = "vertical_line_test" - m = markers.vertical_line(x=x, color=color, linewidth=linewidth) + m = hs.markers.vertical_line(x=x, color=color, linewidth=linewidth) m.name = name s.add_marker(m, permanent=True) s.save(filename) - s1 = load(filename) + s1 = hs.load(filename) m1 = s1.metadata.Markers.get_item(name) assert san_dict(m1._to_dictionary()) == san_dict(m._to_dictionary()) @@ -668,13 +665,13 @@ def test_save_load_vertical_line_segment_marker(self, tmp_path, file): color = "white" linewidth = 4.2 name = "vertical_line_segment_test" - m = markers.vertical_line_segment( + m = hs.markers.vertical_line_segment( x=x, y1=y1, y2=y2, color=color, linewidth=linewidth ) m.name = name s.add_marker(m, permanent=True) s.save(filename) - s1 = load(filename) + s1 = hs.load(filename) m1 = s1.metadata.Markers.get_item(name) assert san_dict(m1._to_dictionary()) == san_dict(m._to_dictionary()) @@ -686,13 +683,13 @@ def test_save_load_line_segment_marker(self, tmp_path, file): color = "cyan" linewidth = 0.7 name = "line_segment_test" - m = markers.line_segment( + m = hs.markers.line_segment( x1=x1, x2=x2, y1=y1, y2=y2, color=color, linewidth=linewidth ) m.name = name s.add_marker(m, permanent=True) s.save(filename) - s1 = load(filename) + s1 = hs.load(filename) m1 = s1.metadata.Markers.get_item(name) assert san_dict(m1._to_dictionary()) == san_dict(m._to_dictionary()) @@ -703,11 +700,11 @@ def test_save_load_point_marker(self, tmp_path, file): x, y = 9, 8 color = "purple" name = "point test" - m = markers.point(x=x, y=y, color=color) + m = hs.markers.point(x=x, y=y, color=color) m.name = name s.add_marker(m, permanent=True) s.save(filename) - s1 = load(filename) + s1 = hs.load(filename) m1 = s1.metadata.Markers.get_item(name) assert san_dict(m1._to_dictionary()) == san_dict(m._to_dictionary()) @@ -719,13 +716,13 @@ def test_save_load_rectangle_marker(self, tmp_path, file): color = "yellow" linewidth = 5 name = "rectangle_test" - m = markers.rectangle( + m = hs.markers.rectangle( x1=x1, x2=x2, y1=y1, y2=y2, color=color, linewidth=linewidth ) m.name = name s.add_marker(m, permanent=True) s.save(filename) - s1 = load(filename) + s1 = hs.load(filename) m1 = s1.metadata.Markers.get_item(name) assert san_dict(m1._to_dictionary()) == san_dict(m._to_dictionary()) @@ -737,11 +734,11 @@ def test_save_load_text_marker(self, tmp_path, file): color = "brown" name = "text_test" text = "a text" - m = markers.text(x=x, y=y, text=text, color=color) + m = hs.markers.text(x=x, y=y, text=text, color=color) m.name = name s.add_marker(m, permanent=True) s.save(filename) - s1 = load(filename) + s1 = hs.load(filename) m1 = s1.metadata.Markers.get_item(name) assert san_dict(m1._to_dictionary()) == san_dict(m._to_dictionary()) @@ -751,14 +748,14 @@ def test_save_load_multidim_navigation_marker(self, tmp_path, file, lazy): filename = tmp_path / file x, y = (1, 2, 3), (5, 6, 7) name = "test point" - s = Signal2D(np.arange(300).reshape(3, 10, 10)) + s = hs.signals.Signal2D(np.arange(300).reshape(3, 10, 10)) if lazy: s = s.as_lazy() - m = markers.point(x=x, y=y) + m = hs.markers.point(x=x, y=y) m.name = name s.add_marker(m, permanent=True) s.save(filename) - s1 = load(filename) + s1 = hs.load(filename) m1 = s1.metadata.Markers.get_item(name) assert san_dict(m1._to_dictionary()) == san_dict(m._to_dictionary()) assert m1.get_data_position("x1") == x[0] @@ -774,7 +771,7 @@ def test_load_unknown_marker_type(self): # test_marker_bad_marker_type.hdf5 has 5 markers, # where one of them has an unknown marker type fname = my_path / "hdf5_files" / "test_marker_bad_marker_type.hdf5" - s = load(fname, reader="HSPY") + s = hs.load(fname, reader="HSPY") assert len(s.metadata.Markers) == 4 def test_load_missing_y2_value(self): @@ -783,7 +780,7 @@ def test_load_missing_y2_value(self): # the point marker only needs the x1 and y1 value to work # so this should load fname = my_path / "hdf5_files" / "test_marker_point_y2_data_deleted.hdf5" - s = load(fname, reader="HSPY") + s = hs.load(fname, reader="HSPY") assert len(s.metadata.Markers) == 5 @@ -793,27 +790,27 @@ def test_save_load_model(tmp_path, file, lazy): from hyperspy._components.gaussian import Gaussian filename = tmp_path / file - s = Signal1D(np.ones((10, 10, 10, 10))) + s = hs.signals.Signal1D(np.ones((10, 10, 10, 10))) if lazy: s = s.as_lazy() m = s.create_model() m.append(Gaussian()) m.store("test") s.save(filename) - signal2 = load(filename) + signal2 = hs.load(filename) m2 = signal2.models.restore("test") assert m.signal == m2.signal @pytest.mark.parametrize("compression", (None, "gzip", "lzf")) def test_compression(compression, tmp_path): - s = Signal1D(np.ones((3, 3))) + s = hs.signals.Signal1D(np.ones((3, 3))) s.save(tmp_path / "test_compression.hspy", overwrite=True, compression=compression) - load(tmp_path / "test_compression.hspy") + _ = hs.load(tmp_path / "test_compression.hspy") def test_strings_from_py2(): - s = EDS_TEM_Spectrum() + s = hs.datasets.example_signals.EDS_TEM_Spectrum() assert isinstance(s.metadata.Sample.elements, list) @@ -821,10 +818,10 @@ def test_strings_from_py2(): def test_save_ragged_array(tmp_path, file): a = np.array([0, 1]) b = np.array([0, 1, 2]) - s = BaseSignal(np.array([a, b], dtype=object), ragged=True) + s = hs.signals.BaseSignal(np.array([a, b], dtype=object), ragged=True) fname = tmp_path / file s.save(fname) - s1 = load(fname) + s1 = hs.load(fname) for i in range(len(s.data)): np.testing.assert_allclose(s.data[i], s1.data[i]) assert s.__class__ == s1.__class__ @@ -836,11 +833,11 @@ def test_save_ragged_dim2(tmp_path, file): for i in range(1, 6): x[i - 1] = np.array([list(range(i)), list(range(i))]) - s = BaseSignal(x, ragged=True) + s = hs.signals.BaseSignal(x, ragged=True) filename = tmp_path / file s.save(filename) - s2 = load(filename) + s2 = hs.load(filename) for i, j in zip(s.data, s2.data): np.testing.assert_array_equal(i, j) @@ -849,7 +846,7 @@ def test_save_ragged_dim2(tmp_path, file): def test_load_missing_extension(caplog): path = my_path / "hdf5_files" / "hspy_ext_missing.hspy" with pytest.warns(UserWarning): - s = load(path) + s = hs.load(path) assert "This file contains a signal provided by the hspy_ext_missing" in caplog.text with pytest.raises(ImportError): _ = s.models.restore("a") @@ -859,7 +856,7 @@ def test_load_missing_extension(caplog): def test_save_chunks_signal_metadata(tmp_path, file): N = 10 dim = 3 - s = Signal1D(np.arange(N**dim).reshape([N] * dim)) + s = hs.signals.Signal1D(np.arange(N**dim).reshape([N] * dim)) s.navigator = s.sum(-1) s.change_dtype("float") s.decomposition() @@ -867,53 +864,53 @@ def test_save_chunks_signal_metadata(tmp_path, file): filename = tmp_path / file chunks = (5, 5, 10) s.save(filename, chunks=chunks) - s2 = load(filename, lazy=True) + s2 = hs.load(filename, lazy=True) assert tuple([c[0] for c in s2.data.chunks]) == chunks @zspy_marker def test_chunking_saving_lazy(tmp_path, file): - s = Signal2D(da.zeros((50, 100, 100))).as_lazy() + s = hs.signals.Signal2D(da.zeros((50, 100, 100))).as_lazy() s.data = s.data.rechunk([50, 25, 25]) filename = tmp_path / "test_chunking_saving_lazy.hspy" filename2 = tmp_path / "test_chunking_saving_lazy_chunks_True.hspy" filename3 = tmp_path / "test_chunking_saving_lazy_chunks_specified.hspy" s.save(filename) - s1 = load(filename, lazy=True) + s1 = hs.load(filename, lazy=True) assert s.data.chunks == s1.data.chunks # with chunks=True, use h5py chunking s.save(filename2, chunks=True) - s2 = load(filename2, lazy=True) + s2 = hs.load(filename2, lazy=True) assert tuple([c[0] for c in s2.data.chunks]) == (7, 25, 25) # specify chunks chunks = (50, 10, 10) s.save(filename3, chunks=chunks) - s3 = load(filename3, lazy=True) + s3 = hs.load(filename3, lazy=True) assert tuple([c[0] for c in s3.data.chunks]) == chunks def test_saving_close_file(tmp_path): # Setup that we will reopen - s = Signal1D(da.zeros((10, 100))).as_lazy() + s = hs.signals.Signal1D(da.zeros((10, 100))).as_lazy() fname = tmp_path / "test.hspy" s.save(fname, close_file=True) - s2 = load(fname, lazy=True, mode="a") + s2 = hs.load(fname, lazy=True, mode="a") assert get_file_handle(s2.data) is not None s2.save(fname, close_file=True, overwrite=True) assert get_file_handle(s2.data) is None - s3 = load(fname, lazy=True, mode="a") + s3 = hs.load(fname, lazy=True, mode="a") assert get_file_handle(s3.data) is not None s3.save(fname, close_file=False, overwrite=True) assert get_file_handle(s3.data) is not None s3.close_file() assert get_file_handle(s3.data) is None - s4 = load(fname, lazy=True) + s4 = hs.load(fname, lazy=True) assert get_file_handle(s4.data) is not None with pytest.raises(OSError): s4.save(fname, overwrite=True) @@ -921,22 +918,22 @@ def test_saving_close_file(tmp_path): @zspy_marker def test_saving_overwrite_data(tmp_path, file): - s = Signal1D(da.zeros((10, 100))).as_lazy() + s = hs.signals.Signal1D(da.zeros((10, 100))).as_lazy() kwds = dict(close_file=True) if file == "test.hspy" else {} fname = tmp_path / file s.save(fname, **kwds) - s2 = load(fname, lazy=True, mode="a") + s2 = hs.load(fname, lazy=True, mode="a") s2.axes_manager[0].units = "nm" s2.data = da.ones((10, 100)) s2.save(fname, overwrite=True, write_dataset=False) - s3 = load(fname) + s3 = hs.load(fname) assert s3.axes_manager[0].units == "nm" # Still old data np.testing.assert_allclose(s3.data, np.zeros((10, 100))) - s4 = load(fname) + s4 = hs.load(fname) s4.data = da.ones((10, 100)) if file == "test.hspy": # try with opening non-lazily to check opening mode @@ -946,17 +943,17 @@ def test_saving_overwrite_data(tmp_path, file): s4.save(fname, overwrite=True, write_dataset=True) # make sure we can open it after, file haven't been corrupted - _ = load(fname) + _ = hs.load(fname) # now new data @zspy_marker def test_chunking_saving_lazy_specify(self, tmp_path, file): filename = tmp_path / file - s = Signal2D(da.zeros((50, 100, 100))).as_lazy() + s = hs.signals.Signal2D(da.zeros((50, 100, 100))).as_lazy() # specify chunks chunks = (50, 10, 10) s.data = s.data.rechunk([50, 25, 25]) s.save(filename, chunks=chunks) - s1 = load(filename, lazy=True) + s1 = hs.load(filename, lazy=True) assert tuple([c[0] for c in s1.data.chunks]) == chunks @@ -994,7 +991,7 @@ def test_get_signal_chunks_small_dataset(): @zspy_marker def test_error_saving(tmp_path, file): filename = tmp_path / file - s = Signal1D(np.arange(10)) + s = hs.signals.Signal1D(np.arange(10)) with pytest.raises(ValueError): s.save(filename, write_dataset="unsupported_type") @@ -1003,12 +1000,12 @@ def test_error_saving(tmp_path, file): def test_more_recent_version_warning(tmp_path): filename = tmp_path / "test.hspy" - s = Signal1D(np.arange(10)) + s = hs.signals.Signal1D(np.arange(10)) s.save(filename) with h5py.File(filename, mode="a") as f: f.attrs["file_format_version"] = "99999999" with pytest.warns(UserWarning): - s2 = load(filename) + s2 = hs.load(filename) np.testing.assert_allclose(s.data, s2.data) diff --git a/rsciio/tests/test_image.py b/rsciio/tests/test_image.py index 158b7e2e1..5f731f4e7 100644 --- a/rsciio/tests/test_image.py +++ b/rsciio/tests/test_image.py @@ -19,7 +19,12 @@ import numpy as np import pytest -import hyperspy.api as hs +try: + import hyperspy.api as hs +except: + pass + +from rsciio.image.api import file_writer @pytest.mark.parametrize(("dtype"), ["uint8", "uint32"]) @@ -198,8 +203,19 @@ def test_save_image_navigation(tmp_path): s.T.save(fname, scalebar=True) +@pytest.mark.no_hyperspy def test_error_library_no_installed(tmp_path): - s = hs.signals.Signal2D(np.arange(128 * 128).reshape(128, 128)) + axis = { + "_type": "UniformDataAxis", + "name": None, + "units": None, + "navigate": False, + "is_binned": False, + "size": 128, + "scale": 1.0, + "offset": 0.0, + } + signal_dict = {"data": np.arange(128 * 128).reshape(128, 128), "axes": [axis, axis]} try: import matplotlib @@ -207,7 +223,9 @@ def test_error_library_no_installed(tmp_path): # When matplotlib is not installed, raises an error to inform user # that matplotlib is necessary with pytest.raises(ValueError): - s.save(tmp_path / "test_image_error.jpg", output_size=64) + file_writer(tmp_path / "test_image_error.jpg", signal_dict, output_size=64) with pytest.raises(ValueError): - s.save(tmp_path / "test_image_error.jpg", imshow_kwds={"a": "b"}) + file_writer( + tmp_path / "test_image_error.jpg", signal_dict, imshow_kwds={"a": "b"} + ) diff --git a/rsciio/tests/test_import.py b/rsciio/tests/test_import.py index ba2067022..760b2c490 100644 --- a/rsciio/tests/test_import.py +++ b/rsciio/tests/test_import.py @@ -34,7 +34,6 @@ def test_import_with_minimal_dependencies_no_hyperspy(): if plugin["format_name"] not in [ "Blockfile", "Electron Microscopy Data (EMD)", - "image", "MRCZ", "Phenom Element Identification (ELID)", "TIFF", diff --git a/rsciio/tests/test_impulse.py b/rsciio/tests/test_impulse.py index bdcd0f569..66f7b5d30 100644 --- a/rsciio/tests/test_impulse.py +++ b/rsciio/tests/test_impulse.py @@ -21,9 +21,11 @@ import numpy as np import pytest -import hyperspy.api as hs from rsciio.impulse.api import ImpulseCSV, invalid_file_error, invalid_filenaming_error +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + + testdirpath = os.path.dirname(__file__) dirpath = os.path.join(testdirpath, "impulse_data") diff --git a/rsciio/tests/test_io.py b/rsciio/tests/test_io.py index bf1238dfd..e09f8b624 100644 --- a/rsciio/tests/test_io.py +++ b/rsciio/tests/test_io.py @@ -26,21 +26,19 @@ import numpy as np import pytest -import hyperspy.api as hs -from hyperspy.signals import Signal1D -from hyperspy.axes import DataAxis from rsciio import IO_PLUGINS -from hyperspy import __version__ as hs_version -from hyperspy.misc.test_utils import assert_deep_almost_equal +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + +from hyperspy.axes import DataAxis FULLFILENAME = Path(__file__).resolve().parent.joinpath("test_io_overwriting.hspy") class TestIOOverwriting: def setup_method(self, method): - self.s = Signal1D(np.arange(10)) - self.new_s = Signal1D(np.ones(5)) + self.s = hs.signals.Signal1D(np.arange(10)) + self.new_s = hs.signals.Signal1D(np.ones(5)) # make sure we start from a clean state self._clean_file() self.s.save(FULLFILENAME) @@ -100,7 +98,7 @@ def teardown_method(self, method): class TestNonUniformAxisCheck: def setup_method(self, method): axis = DataAxis(axis=1 / (np.arange(10) + 1), navigate=False) - self.s = Signal1D(np.arange(10), axes=(axis.get_axis_dictionary(),)) + self.s = hs.signals.Signal1D(np.arange(10), axes=(axis.get_axis_dictionary(),)) # make sure we start from a clean state def test_io_nonuniform(self): @@ -142,7 +140,7 @@ def teardown_method(self): def test_glob_wildcards(): - s = Signal1D(np.arange(10)) + s = hs.signals.Signal1D(np.arange(10)) with tempfile.TemporaryDirectory() as dirpath: fnames = [os.path.join(dirpath, f"temp[1x{x}].hspy") for x in range(2)] @@ -201,7 +199,7 @@ def test_file_not_found_error(): def test_file_reader_error(): # Only None, str or objects with attr "file_reader" are supported - s = Signal1D(np.arange(10)) + s = hs.signals.Signal1D(np.arange(10)) with tempfile.TemporaryDirectory() as dirpath: f = os.path.join(dirpath, "temp.hspy") @@ -213,7 +211,7 @@ def test_file_reader_error(): def test_file_reader_warning(caplog): # Test fallback to Pillow imaging library - s = Signal1D(np.arange(10)) + s = hs.signals.Signal1D(np.arange(10)) with tempfile.TemporaryDirectory() as dirpath: f = os.path.join(dirpath, "temp.hspy") @@ -227,7 +225,7 @@ def test_file_reader_warning(caplog): def test_file_reader_options(): - s = Signal1D(np.arange(10)) + s = hs.signals.Signal1D(np.arange(10)) with tempfile.TemporaryDirectory() as dirpath: f = os.path.join(dirpath, "temp.hspy") @@ -247,7 +245,7 @@ def test_file_reader_options(): def test_save_default_format(): - s = Signal1D(np.arange(10)) + s = hs.signals.Signal1D(np.arange(10)) with tempfile.TemporaryDirectory() as dirpath: f = os.path.join(dirpath, "temp") @@ -258,7 +256,7 @@ def test_save_default_format(): def test_load_original_metadata(): - s = Signal1D(np.arange(10)) + s = hs.signals.Signal1D(np.arange(10)) s.original_metadata.a = 0 with tempfile.TemporaryDirectory() as dirpath: @@ -283,7 +281,7 @@ def test_load_save_filereader_metadata(): s = hs.load(os.path.join(my_path, "msa_files", "example1.msa")) assert s.metadata.General.FileIO.Number_0.io_plugin == "rsciio.msa.api" assert s.metadata.General.FileIO.Number_0.operation == "load" - assert s.metadata.General.FileIO.Number_0.hyperspy_version == hs_version + assert s.metadata.General.FileIO.Number_0.hyperspy_version == hs.__version__ with tempfile.TemporaryDirectory() as dirpath: f = os.path.join(dirpath, "temp") @@ -292,17 +290,17 @@ def test_load_save_filereader_metadata(): "0": { "io_plugin": "rsciio.msa.api", "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, }, "1": { "io_plugin": "rsciio.hspy.api", "operation": "save", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, }, "2": { "io_plugin": "rsciio.hspy.api", "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, }, } del s.metadata.General.FileIO.Number_0.timestamp # runtime dependent diff --git a/rsciio/tests/test_jeol.py b/rsciio/tests/test_jeol.py index 1c5b581e2..5cd0dc209 100644 --- a/rsciio/tests/test_jeol.py +++ b/rsciio/tests/test_jeol.py @@ -22,8 +22,7 @@ import pytest import numpy as np -import hyperspy.api as hs -from hyperspy import __version__ as hs_version +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") def teardown_module(module): @@ -287,7 +286,7 @@ def test_load_eds_file(filename_as_string): "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.jeol.api", } }, diff --git a/rsciio/tests/test_mrcz.py b/rsciio/tests/test_mrcz.py index 6511ac43e..a9df5a207 100644 --- a/rsciio/tests/test_mrcz.py +++ b/rsciio/tests/test_mrcz.py @@ -25,15 +25,13 @@ import pytest from datetime import datetime -from hyperspy import signals -from hyperspy.io import load, save -from hyperspy.misc.test_utils import assert_deep_almost_equal -from hyperspy import __version__ as hs_version - +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") mrcz = pytest.importorskip("mrcz", reason="mrcz not installed") +from hyperspy.misc.test_utils import assert_deep_almost_equal + # ============================================================================== # MRCZ Test # @@ -69,6 +67,7 @@ def compareSaveLoad( do_async=False, **kwargs ): + # This is the main function which reads and writes from disk. mrcName = os.path.join(tmpDir, "testMage_{}_lazy_{}.mrcz".format(dtype, lazy)) @@ -82,7 +81,7 @@ def compareSaveLoad( else: # integers testData = np.random.randint(10, size=testShape).astype(dtype) - testSignal = signals.Signal2D(testData) + testSignal = hs.signals.Signal2D(testData) if lazy: testSignal = testSignal.as_lazy() @@ -92,7 +91,7 @@ def compareSaveLoad( "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.mrcz", "timestamp": datetime.now().astimezone().isoformat(), } @@ -120,13 +119,8 @@ def compareSaveLoad( "Signal.Noise_properties.Variance_linear_model.gain_factor", 1.0 ) - save( - mrcName, - testSignal, - compressor=compressor, - clevel=clevel, - do_async=do_async, - **kwargs + testSignal.save( + mrcName, compressor=compressor, clevel=clevel, do_async=do_async, **kwargs ) if do_async: # Poll file on disk since we don't return the @@ -147,7 +141,7 @@ def compareSaveLoad( ) sleep(0.1) - reSignal = load(mrcName) + reSignal = hs.load(mrcName) try: os.remove(mrcName) except IOError: @@ -178,9 +172,9 @@ def compareSaveLoad( ) if dtype == "complex64": - assert isinstance(reSignal, signals.ComplexSignal2D) + assert isinstance(reSignal, hs.signals.ComplexSignal2D) else: - assert isinstance(reSignal, signals.Signal2D) + assert isinstance(reSignal, hs.signals.Signal2D) # delete last load operation from reSignal metadata so we can compare del reSignal.metadata.General.FileIO.Number_2 @@ -232,9 +226,7 @@ def test_MRC(self, dtype, compressor, clevel, lazy): @pytest.mark.parametrize("dtype", dtype_list) def test_Async(self, dtype): - blosc = pytest.importorskip( - "blosc", reason="skipping test_async, requires blosc" - ) + _ = pytest.importorskip("blosc", reason="skipping test_async, requires blosc") t_start = perf_counter() self.compareSaveLoad( [2, 64, 32], dtype=dtype, compressor="zstd", clevel=1, do_async=True diff --git a/rsciio/tests/test_msa.py b/rsciio/tests/test_msa.py index c0053dad4..e78db88ed 100644 --- a/rsciio/tests/test_msa.py +++ b/rsciio/tests/test_msa.py @@ -1,10 +1,12 @@ import copy import os.path import tempfile +import pytest + +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") -from hyperspy.io import load from hyperspy.misc.test_utils import assert_deep_almost_equal -from hyperspy import __version__ as hs_version + my_path = os.path.dirname(__file__) @@ -35,7 +37,7 @@ "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.msa.api", } }, @@ -132,7 +134,7 @@ "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.msa.api", } }, @@ -197,7 +199,7 @@ class TestExample1: def setup_method(self, method): - self.s = load(os.path.join(my_path, "msa_files", "example1.msa")) + self.s = hs.load(os.path.join(my_path, "msa_files", "example1.msa")) # delete timestamp from metadata since it's runtime dependent del self.s.metadata.General.FileIO.Number_0.timestamp @@ -236,7 +238,7 @@ def test_write_load_cycle(self): with tempfile.TemporaryDirectory() as tmpdir: fname2 = os.path.join(tmpdir, "example1-export.msa") self.s.save(fname2) - s2 = load(fname2) + s2 = hs.load(fname2) # delete timestamp from metadata since it's runtime dependent del s2.metadata.General.FileIO.Number_0.timestamp del self.s.metadata.General.FileIO.Number_1 @@ -251,7 +253,7 @@ def test_write_load_cycle(self): class TestExample1WrongDate: def setup_method(self, method): - self.s = load(os.path.join(my_path, "msa_files", "example1_wrong_date.msa")) + self.s = hs.load(os.path.join(my_path, "msa_files", "example1_wrong_date.msa")) # delete timestamp from metadata since it's runtime dependent del self.s.metadata.General.FileIO.Number_0.timestamp @@ -265,7 +267,7 @@ def test_metadata(self): class TestExample2: def setup_method(self, method): - self.s = load(os.path.join(my_path, "msa_files", "example2.msa")) + self.s = hs.load(os.path.join(my_path, "msa_files", "example2.msa")) # delete timestamp from metadata since it's runtime dependent del self.s.metadata.General.FileIO.Number_0.timestamp @@ -363,7 +365,7 @@ def test_write_load_cycle(self): with tempfile.TemporaryDirectory() as tmpdir: fname2 = os.path.join(tmpdir, "example2-export.msa") self.s.save(fname2) - s2 = load(fname2) + s2 = hs.load(fname2) assert s2.metadata.General.original_filename == "example2-export.msa" s2.metadata.General.original_filename = "example2.msa" # delete timestamp from metadata since it's runtime dependent @@ -375,5 +377,5 @@ def test_write_load_cycle(self): def test_minimum_metadata_example(): - s = load(os.path.join(my_path, "msa_files", "minimum_metadata.msa")) + s = hs.load(os.path.join(my_path, "msa_files", "minimum_metadata.msa")) assert minimum_md_om == s.original_metadata.as_dictionary() diff --git a/rsciio/tests/test_nexus_hdf.py b/rsciio/tests/test_nexus_hdf.py index 7e3ca699b..375412edc 100644 --- a/rsciio/tests/test_nexus_hdf.py +++ b/rsciio/tests/test_nexus_hdf.py @@ -20,15 +20,15 @@ import numpy as np import pytest + +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + import traits.api as t import h5py -import hyperspy.api as hs -from hyperspy._signals.signal1d import Signal1D -from hyperspy._signals.signal2d import Signal2D -from rsciio.exceptions import VisibleDeprecationWarning from hyperspy.exceptions import VisibleDeprecationWarning as HSVisibleDeprecationWarning -from hyperspy.io import load + +from rsciio.exceptions import VisibleDeprecationWarning from rsciio.nexus.api import ( _byte_to_string, _fix_exclusion_keys, @@ -62,7 +62,7 @@ class TestDLSNexus: def setup_method(self, method): self.file = file3 - self.s = load( + self.s = hs.load( file3, metadata_key=None, dataset_key=None, @@ -73,7 +73,7 @@ def setup_method(self, method): @pytest.mark.parametrize("nxdata_only", [True, False]) @pytest.mark.parametrize("hardlinks_only", [True, False]) def test_nxdata_only(self, nxdata_only, hardlinks_only): - s = load(self.file, nxdata_only=nxdata_only, hardlinks_only=hardlinks_only) + s = hs.load(self.file, nxdata_only=nxdata_only, hardlinks_only=hardlinks_only) if nxdata_only and not hardlinks_only: assert len(s) == 2 if nxdata_only and hardlinks_only: @@ -85,7 +85,7 @@ def test_nxdata_only(self, nxdata_only, hardlinks_only): @pytest.mark.parametrize("metadata_key", ["m1_y", "xxxx"]) def test_metadata_keys(self, metadata_key): - s = load(file3, nxdata_only=True, metadata_key=metadata_key) + s = hs.load(file3, nxdata_only=True, metadata_key=metadata_key) # hardlinks are false - soft linked data is loaded if metadata_key == "m1_y": assert s[1].original_metadata.alias_metadata.m1_y.attrs.units == "mm" @@ -119,12 +119,12 @@ def test_save_hspy(self, tmp_path): ("/entry1/testdata/nexustest", ["/entry1/testdata/nexustest", "wrong"]), ) def test_dataset_paths(self, dataset_path): - s = load(self.file, dataset_path=dataset_path) + s = hs.load(self.file, dataset_path=dataset_path) title = s.metadata.General.title assert title == "nexustest" def test_skip_load_array_metadata(self): - s = load( + s = hs.load( self.file, nxdata_only=True, hardlinks_only=True, @@ -136,25 +136,25 @@ def test_skip_load_array_metadata(self): def test_deprecated_metadata_keys(self): with pytest.warns(VisibleDeprecationWarning): - load(self.file, metadata_keys="stage1_x") + _ = hs.load(self.file, metadata_keys="stage1_x") def test_deprecated_dataset_keys(self): with pytest.warns(VisibleDeprecationWarning): - load(self.file, dataset_keys="rocks") + _ = hs.load(self.file, dataset_keys="rocks") def test_deprecated_dataset_paths(self): with pytest.warns(VisibleDeprecationWarning): - load(self.file, dataset_paths="/entry1/testdata/nexustest/data") + _ = hs.load(self.file, dataset_paths="/entry1/testdata/nexustest/data") class TestDLSNexusNoAxes: def setup_method(self, method): self.file = file4 - self.s = load(file4, hardlinks_only=True, nxdata_only=True) + self.s = hs.load(file4, hardlinks_only=True, nxdata_only=True) @pytest.mark.parametrize("metadata_key", [None, "m1_x"]) def test_meta_keys(self, metadata_key): - s = load(file3, nxdata_only=True, metadata_key=metadata_key) + s = hs.load(file3, nxdata_only=True, metadata_key=metadata_key) # hardlinks are false - soft linked data is loaded if metadata_key is None: assert ( @@ -195,7 +195,7 @@ def test_save_hspy(self, tmp_path): class TestSavedSignalLoad: def setup_method(self, method): with pytest.warns(HSVisibleDeprecationWarning): - self.s = load(file1, nxdata_only=True) + self.s = hs.load(file1, nxdata_only=True) def test_string(self): assert self.s.original_metadata.instrument.energy.attrs.units == "keV" @@ -226,7 +226,7 @@ def test_axes_names(self): class TestSavedMultiSignalLoad: def setup_method(self, method): with pytest.warns(HSVisibleDeprecationWarning): - self.s = load( + self.s = hs.load( file2, nxdata_only=True, hardlinks_only=True, use_default=False ) @@ -288,7 +288,7 @@ def test_save_scalers(self, tmp_path): s.original_metadata.set_item("test3", 64.0) fname = tmp_path / "test.nxs" s.save(fname) - lin = load(fname, nxdata_only=True) + lin = hs.load(fname, nxdata_only=True) assert isinstance(lin.original_metadata.test1, float) assert isinstance(lin.original_metadata.test2, float) assert isinstance(lin.original_metadata.test3, float) @@ -301,7 +301,7 @@ def test_save_arrays(self, tmp_path): s.original_metadata.set_item("testarray3", np.array([1, 2, 3, 4, 5])) fname = tmp_path / "test.nxs" s.save(fname) - lin = load(fname, nxdata_only=True) + lin = hs.load(fname, nxdata_only=True) np.testing.assert_array_equal( lin.original_metadata.testarray1, np.array([b"a", b"2", b"b", b"4", b"5"]) ) @@ -319,7 +319,7 @@ def test_save_original_metadata(self, tmp_path): s.original_metadata.set_item("testarray3", np.array([1, 2, 3, 4, 5])) fname = tmp_path / "test.nxs" s.save(fname, save_original_metadata=False) - lin = load(fname, nxdata_only=True) + lin = hs.load(fname, nxdata_only=True) with pytest.raises(AttributeError): lin.original_metadata.testarray1 @@ -330,7 +330,7 @@ def test_save_skip_original_metadata_keys(self, tmp_path): s.original_metadata.set_item("testarray3", np.array([1, 2, 3, 4, 5])) fname = tmp_path / "test.nxs" s.save(fname, skip_metadata_key="testarray2") - lin = load(fname, nxdata_only=True) + lin = hs.load(fname, nxdata_only=True) with pytest.raises(AttributeError): lin.original_metadata.testarray2 @@ -346,7 +346,7 @@ def test_save_without_default_load_with_default(self, tmp_path): s = self.s fname = tmp_path / "test.nxs" s.save(fname, use_default=False) - lin = load(fname, nxdata_only=True, use_default=True) + lin = hs.load(fname, nxdata_only=True, use_default=True) assert np.isclose(lin.data, s.data).all() def test_save_metadata_as_dict(self, tmp_path): @@ -367,7 +367,7 @@ def test_save_metadata_as_dict(self, tmp_path): fname = tmp_path / "test.nxs" s.save(fname) - lin = load(fname, nxdata_only=True) + lin = hs.load(fname, nxdata_only=True) np.testing.assert_array_equal( lin.original_metadata.testarray1, np.array([b"a", b"2", b"b", b"4", b"5"]) ) @@ -382,10 +382,12 @@ def test_save_hyperspy_signal_metadata(self, tmp_path): s = self.s s.original_metadata.set_item("testarray1", BaseSignal([1.2, 2.3, 3.4])) s.original_metadata.set_item("testarray2", (1, 2, 3, 4, 5)) - s.original_metadata.set_item("testarray3", Signal2D(np.ones((2, 3, 5, 4)))) + s.original_metadata.set_item( + "testarray3", hs.signals.Signal2D(np.ones((2, 3, 5, 4))) + ) fname = tmp_path / "test.nxs" s.save(fname) - lin = load(fname, nxdata_only=True) + lin = hs.load(fname, nxdata_only=True) np.testing.assert_allclose( lin.original_metadata.testarray1.data, np.array([1.2, 2.3, 3.4]) ) @@ -400,7 +402,7 @@ def test_save_3D_signal(self, tmp_path): s = BaseSignal(np.zeros((2, 3, 4))) fname = tmp_path / "test.nxs" s.save(fname) - lin = load(fname, nxdata_only=True) + lin = hs.load(fname, nxdata_only=True) assert lin.axes_manager.signal_dimension == 3 np.testing.assert_array_equal(lin.data, np.zeros((2, 3, 4))) @@ -409,7 +411,7 @@ def test_save_title_with_slash(self, tmp_path): s.metadata.General.title = "/entry/something" fname = tmp_path / "test.nxs" s.save(fname) - lin = load(fname, nxdata_only=True) + lin = hs.load(fname, nxdata_only=True) assert lin.metadata.General.title == "_entry_something" def test_save_title_double_underscore(self, tmp_path): @@ -417,7 +419,7 @@ def test_save_title_double_underscore(self, tmp_path): s.metadata.General.title = "__entry/something" fname = tmp_path / "test.nxs" s.save(fname) - lin = load(fname, nxdata_only=True) + lin = hs.load(fname, nxdata_only=True) assert lin.metadata.General.title == "entry_something" @@ -439,14 +441,14 @@ def test_saving_multi_signals(tmp_path): fname = tmp_path / "test.nxs" sig.save(fname) file_writer(fname, [sig._to_dictionary(), sig2._to_dictionary()]) - lin = load(fname, nxdata_only=True) + lin = hs.load(fname, nxdata_only=True) assert len(lin) == 2 assert lin[0].original_metadata.stage_y.value == 4.0 assert lin[0].axes_manager[0].name == "stage_y_axis" assert lin[1].original_metadata.stage_x.value == 8.0 assert lin[1].original_metadata.stage_x.attrs.units == "mm" - assert isinstance(lin[0], Signal2D) - assert isinstance(lin[1], Signal1D) + assert isinstance(lin[0], hs.signals.Signal2D) + assert isinstance(lin[1], hs.signals.Signal1D) # test the metadata haven't merged with pytest.raises(AttributeError): lin[1].original_metadata.stage_y.value @@ -608,8 +610,8 @@ def test_dataset_with_chunks_attrs(): def test_extract_hdf5(): - s = load(file5, lazy=False) - s_lazy = load(file5, lazy=True) + s = hs.load(file5, lazy=False) + s_lazy = hs.load(file5, lazy=True) assert len(s) == 6 assert len(s_lazy) == 6 diff --git a/rsciio/tests/test_panta_rhei.py b/rsciio/tests/test_panta_rhei.py index 168b969d8..329efc49c 100644 --- a/rsciio/tests/test_panta_rhei.py +++ b/rsciio/tests/test_panta_rhei.py @@ -18,9 +18,11 @@ from pathlib import Path + import numpy as np +import pytest -import hyperspy.api as hs +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") from hyperspy.misc.test_utils import assert_deep_almost_equal my_path = Path(__file__).parent diff --git a/rsciio/tests/test_phenom.py b/rsciio/tests/test_phenom.py index 77d7ac674..4a5630f5d 100644 --- a/rsciio/tests/test_phenom.py +++ b/rsciio/tests/test_phenom.py @@ -21,8 +21,7 @@ import pytest -import hyperspy.api as hs - +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") imagecodecs = pytest.importorskip( "imagecodecs", reason="skipping test_phenom tests, requires imagecodecs" ) diff --git a/rsciio/tests/test_protochips.py b/rsciio/tests/test_protochips.py index aaba834dd..ff0ccafc7 100644 --- a/rsciio/tests/test_protochips.py +++ b/rsciio/tests/test_protochips.py @@ -21,7 +21,8 @@ import numpy as np import pytest -import hyperspy.api as hs +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + from rsciio.protochips.api import ProtochipsCSV, invalid_file_error testdirpath = os.path.dirname(__file__) diff --git a/rsciio/tests/test_ripple.py b/rsciio/tests/test_ripple.py index 1d26afd84..a225f2891 100644 --- a/rsciio/tests/test_ripple.py +++ b/rsciio/tests/test_ripple.py @@ -6,8 +6,8 @@ import numpy.testing as npt import pytest -import hyperspy.signals as signals -from hyperspy.io import load +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + from rsciio.ripple import api as ripple # Tuple of tuples (data shape, signal_dimensions) @@ -22,14 +22,14 @@ def test_write_unsupported_data_shape(): data = np.arange(5 * 10 * 15 * 20).reshape((5, 10, 15, 20)) - s = signals.Signal1D(data) + s = hs.signals.Signal1D(data) with pytest.raises(TypeError): s.save("test_write_unsupported_data_shape.rpl") def test_write_unsupported_data_type(): data = np.arange(5 * 10 * 15).reshape((5, 10, 15)).astype(np.float16) - s = signals.Signal1D(data) + s = hs.signals.Signal1D(data) with pytest.raises(IOError): s.save("test_write_unsupported_data_type.rpl") @@ -38,20 +38,20 @@ def test_write_unsupported_data_type(): # def test_write_scalar(): # data = np.array([2]) # with tempfile.TemporaryDirectory() as tmpdir: -# s = signals.BaseSignal(data) +# s = hs.signals.BaseSignal(data) # fname = os.path.join(tmpdir, 'test_write_scalar_data.rpl') # s.save(fname) -# s2 = load(fname) +# s2 = hs.load(fname) # np.testing.assert_allclose(s.data, s2.data) def test_write_without_metadata(): data = np.arange(5 * 10 * 15).reshape((5, 10, 15)) - s = signals.Signal1D(data) + s = hs.signals.Signal1D(data) with tempfile.TemporaryDirectory() as tmpdir: fname = os.path.join(tmpdir, "test_write_without_metadata.rpl") s.save(fname) - s2 = load(fname) + s2 = hs.load(fname) np.testing.assert_allclose(s.data, s2.data) # for windows del s2 @@ -60,14 +60,14 @@ def test_write_without_metadata(): def test_write_with_metadata(): data = np.arange(5 * 10).reshape((5, 10)) - s = signals.Signal1D(data) + s = hs.signals.Signal1D(data) s.metadata.set_item("General.date", "2016-08-06") s.metadata.set_item("General.time", "10:55:00") s.metadata.set_item("General.title", "Test title") with tempfile.TemporaryDirectory() as tmpdir: fname = os.path.join(tmpdir, "test_write_with_metadata.rpl") s.save(fname) - s2 = load(fname) + s2 = hs.load(fname) np.testing.assert_allclose(s.data, s2.data) assert s.metadata.General.date == s2.metadata.General.date assert s.metadata.General.title == s2.metadata.General.title @@ -107,13 +107,13 @@ def _create_signal(shape, dim, dtype, metadata): data = np.arange(np.product(shape)).reshape(shape).astype(dtype) if dim == 1: if len(shape) > 2: - s = signals.EELSSpectrum(data) + s = hs.signals.EELSSpectrum(data) if metadata: s.set_microscope_parameters( beam_energy=100.0, convergence_angle=1.0, collection_angle=10.0 ) else: - s = signals.EDSTEMSpectrum(data) + s = hs.signals.EDSTEMSpectrum(data) if metadata: s.set_microscope_parameters( beam_energy=100.0, @@ -124,7 +124,7 @@ def _create_signal(shape, dim, dtype, metadata): energy_resolution_MnKa=5.0, ) else: - s = signals.BaseSignal(data).transpose(signal_axes=dim) + s = hs.signals.BaseSignal(data).transpose(signal_axes=dim) if metadata: s.metadata.General.date = "2016-08-06" s.metadata.General.time = "10:55:00" @@ -154,8 +154,8 @@ def test_data(pdict): s = _create_signal(shape=shape, dim=dim, dtype=dtype, metadata=metadata) filename = _get_filename(s, metadata) s.save(os.path.join(tmpdir, filename)) - s_just_saved = load(os.path.join(tmpdir, filename)) - s_ref = load(os.path.join(MYPATH, "ripple_files", filename)) + s_just_saved = hs.load(os.path.join(tmpdir, filename)) + s_ref = hs.load(os.path.join(MYPATH, "ripple_files", filename)) try: for stest in (s_just_saved, s_ref): npt.assert_array_equal(s.data, stest.data) diff --git a/rsciio/tests/test_semper_unf.py b/rsciio/tests/test_semper_unf.py index 14660f210..e378b98c9 100644 --- a/rsciio/tests/test_semper_unf.py +++ b/rsciio/tests/test_semper_unf.py @@ -23,8 +23,7 @@ import numpy as np import pytest -from hyperspy.io import load -from hyperspy.signals import BaseSignal, ComplexSignal, Signal1D, Signal2D +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") my_path = os.path.dirname(__file__) @@ -43,7 +42,7 @@ def test_writing_unsupported_data_type(): data = np.arange(5 * 10).reshape((5, 10)) - s = BaseSignal(data.astype("int64")) + s = hs.signals.BaseSignal(data.astype("int64")) with tempfile.TemporaryDirectory() as tmpdir: with pytest.raises(IOError) as cm: fname = os.path.join(tmpdir, "test_writing_unsupported_data_type.unf") @@ -55,93 +54,93 @@ def test_writing_unsupported_data_type(): def test_writing_loading_metadata(): data = np.arange(5 * 10).reshape((5, 10)).astype(np.int8) - s = BaseSignal(data) + s = hs.signals.BaseSignal(data) s.metadata.set_item("General.date", "2016-08-06") s.metadata.set_item("General.time", "11:55:00") with tempfile.TemporaryDirectory() as tmpdir: fname = os.path.join(tmpdir, "test_write_with_metadata.unf") s.save(fname) - s2 = load(fname) + s2 = hs.load(fname) np.testing.assert_allclose(s.data, s2.data) assert s.metadata.General.date == s2.metadata.General.date assert s.metadata.General.time == s2.metadata.General.time def test_signal_3d_loading(): - signal = load(os.path.join(my_path, "unf_files", "example_signal_3d.unf")) + signal = hs.load(os.path.join(my_path, "unf_files", "example_signal_3d.unf")) np.testing.assert_equal(signal.data, data_signal) np.testing.assert_equal(signal.original_metadata.IFORM, 2) # float - assert isinstance(signal, BaseSignal) + assert isinstance(signal, hs.signals.BaseSignal) def test_image_2d_loading(): - signal = load(os.path.join(my_path, "unf_files", "example_image_2d.unf")) + signal = hs.load(os.path.join(my_path, "unf_files", "example_image_2d.unf")) np.testing.assert_equal(signal.data, data_image) np.testing.assert_equal(signal.original_metadata.IFORM, 2) # float - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) def test_spectrum_1d_loading(): - signal = load(os.path.join(my_path, "unf_files", "example_spectrum_1d.unf")) + signal = hs.load(os.path.join(my_path, "unf_files", "example_spectrum_1d.unf")) np.testing.assert_equal(signal.data, data_spectrum) np.testing.assert_equal(signal.original_metadata.IFORM, 2) # float - assert isinstance(signal, Signal1D) + assert isinstance(signal, hs.signals.Signal1D) def test_image_byte_loading(): - signal = load(os.path.join(my_path, "unf_files", "example_image_byte.unf")) + signal = hs.load(os.path.join(my_path, "unf_files", "example_image_byte.unf")) np.testing.assert_equal(signal.data, data_image_byte) np.testing.assert_equal(signal.original_metadata.IFORM, 0) # byte - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) def test_image_int16_loading(): - signal = load(os.path.join(my_path, "unf_files", "example_image_int16.unf")) + signal = hs.load(os.path.join(my_path, "unf_files", "example_image_int16.unf")) np.testing.assert_equal(signal.data, data_image_int16) np.testing.assert_equal(signal.original_metadata.IFORM, 1) # int16 - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) def test_image_int32_loading(): - signal = load(os.path.join(my_path, "unf_files", "example_image_int32.unf")) + signal = hs.load(os.path.join(my_path, "unf_files", "example_image_int32.unf")) np.testing.assert_equal(signal.data, data_image_int32) np.testing.assert_equal(signal.original_metadata.IFORM, 4) # int32 - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) def test_image_complex_loading(): - signal = load(os.path.join(my_path, "unf_files", "example_image_complex.unf")) + signal = hs.load(os.path.join(my_path, "unf_files", "example_image_complex.unf")) np.testing.assert_equal(signal.data, data_image_complex) np.testing.assert_equal(signal.original_metadata.IFORM, 3) # complex - assert isinstance(signal, ComplexSignal) + assert isinstance(signal, hs.signals.ComplexSignal) def test_with_title_loading(): - signal = load(os.path.join(my_path, "unf_files", "example_with_title.unf")) + signal = hs.load(os.path.join(my_path, "unf_files", "example_with_title.unf")) np.testing.assert_equal(signal.data, data_image) np.testing.assert_equal(signal.original_metadata.IFORM, 2) # float np.testing.assert_equal(signal.metadata.General.title, test_title) - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) def test_no_label_loading(): - signal = load(os.path.join(my_path, "unf_files", "example_no_label.unf")) + signal = hs.load(os.path.join(my_path, "unf_files", "example_no_label.unf")) np.testing.assert_equal(signal.data, data_image) np.testing.assert_equal(signal.original_metadata.ILABEL, 0) - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) class TestCaseSaveAndReadImage: def test_save_and_read(self): - signal_ref = Signal2D(data_image) + signal_ref = hs.signals.Signal2D(data_image) signal_ref.metadata.General.title = test_title signal_ref.save( os.path.join(my_path, "unf_files", "example_temp.unf"), overwrite=True ) - signal = load(os.path.join(my_path, "unf_files", "example_temp.unf")) + signal = hs.load(os.path.join(my_path, "unf_files", "example_temp.unf")) np.testing.assert_equal(signal.data, signal_ref.data) np.testing.assert_equal(signal.metadata.General.title, test_title) - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) def teardown_method(self, method): remove(os.path.join(my_path, "unf_files", "example_temp.unf")) @@ -149,15 +148,15 @@ def teardown_method(self, method): class TestCaseSaveAndReadByte: def test_save_and_read(self): - signal_ref = Signal2D(data_image_byte) + signal_ref = hs.signals.Signal2D(data_image_byte) signal_ref.metadata.General.title = test_title signal_ref.save( os.path.join(my_path, "unf_files", "example_temp.unf"), overwrite=True ) - signal = load(os.path.join(my_path, "unf_files", "example_temp.unf")) + signal = hs.load(os.path.join(my_path, "unf_files", "example_temp.unf")) np.testing.assert_equal(signal.data, signal_ref.data) np.testing.assert_equal(signal.metadata.General.title, test_title) - assert isinstance(signal, Signal2D) + assert isinstance(signal, hs.signals.Signal2D) def teardown_method(self, method): remove(os.path.join(my_path, "unf_files", "example_temp.unf")) diff --git a/rsciio/tests/test_sur.py b/rsciio/tests/test_sur.py index 548f2a463..c95740b22 100644 --- a/rsciio/tests/test_sur.py +++ b/rsciio/tests/test_sur.py @@ -19,8 +19,10 @@ import os import numpy as np +import pytest + +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") -from hyperspy.io import load MY_PATH = os.path.dirname(__file__) @@ -140,7 +142,7 @@ def test_load_profile(): # Signal loading fname = os.path.join(MY_PATH, "sur_data", "test_profile.pro") - s = load(fname) + s = hs.load(fname) # Verifying signal shape and axes dimensions, navigation (not data themselves) assert s.data.shape == (128,) @@ -166,7 +168,7 @@ def test_load_profile(): def test_load_RGB(): fname = os.path.join(MY_PATH, "sur_data", "test_RGB.sur") - s = load(fname) + s = hs.load(fname) assert s.data.shape == (200, 200) assert s.data.dtype == np.dtype([("R", "u1"), ("G", "u1"), ("B", "u1")]) @@ -198,7 +200,7 @@ def test_load_RGB(): def test_load_spectra(): fname = os.path.join(MY_PATH, "sur_data", "test_spectra.pro") - s = load(fname) + s = hs.load(fname) assert s.data.shape == (65, 512) assert s.data.dtype == np.dtype("float64") @@ -228,7 +230,7 @@ def test_load_spectra(): def test_load_spectral_map_compressed(): fname = os.path.join(MY_PATH, "sur_data", "test_spectral_map_compressed.sur") - s = load(fname) + s = hs.load(fname) assert s.data.shape == (12, 10, 281) assert s.data.dtype == np.dtype("float64") @@ -276,7 +278,7 @@ def test_load_spectral_map_compressed(): def test_load_spectral_map(): fname = os.path.join(MY_PATH, "sur_data", "test_spectral_map.sur") - s = load(fname) + s = hs.load(fname) assert s.data.shape == (12, 10, 310) assert s.data.dtype == np.dtype("float64") @@ -324,7 +326,7 @@ def test_load_spectral_map(): def test_load_spectrum_compressed(): fname = os.path.join(MY_PATH, "sur_data", "test_spectrum_compressed.pro") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Signal.quantity == "CL Intensity (a.u.)" assert s.data.shape == (512,) @@ -350,7 +352,7 @@ def test_load_spectrum_compressed(): def test_load_spectrum(): fname = os.path.join(MY_PATH, "sur_data", "test_spectrum.pro") - s = load(fname) + s = hs.load(fname) assert s.data.shape == (512,) md = s.metadata @@ -377,7 +379,7 @@ def test_load_spectrum(): def test_load_surface(): fname = os.path.join(MY_PATH, "sur_data", "test_surface.sur") - s = load(fname) + s = hs.load(fname) md = s.metadata assert md.Signal.quantity == "CL Intensity (a.u.)" assert s.data.shape == (128, 128) diff --git a/rsciio/tests/test_tiff.py b/rsciio/tests/test_tiff.py index b15250197..fda6d2fdd 100644 --- a/rsciio/tests/test_tiff.py +++ b/rsciio/tests/test_tiff.py @@ -1,3 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2007-2022 The HyperSpy developers +# +# This file is part of RosettaSciIO. +# +# RosettaSciIO is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# RosettaSciIO is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with RosettaSciIO. If not, see . + + import os from packaging.version import Version from pathlib import Path @@ -5,15 +24,16 @@ import warnings import zipfile - import numpy as np import pytest + +tifffile = pytest.importorskip("tifffile", reason="tifffile not installed") +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + import traits.api as t -import tifffile -import hyperspy.api as hs from hyperspy.misc.test_utils import assert_deep_almost_equal -from hyperspy import __version__ as hs_version + import rsciio.tiff @@ -393,7 +413,7 @@ def test_saving_loading_stack_no_scale(): "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.tiff.api", } }, @@ -568,7 +588,7 @@ def test_read_Zeiss_SEM_scale_metadata_1k_image(self): "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.tiff.api", } }, @@ -622,7 +642,7 @@ def test_read_Zeiss_SEM_scale_metadata_512_image(self): "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.tiff.api", } }, @@ -664,7 +684,7 @@ def test_read_RGB_Zeiss_optical_scale_metadata(): np.testing.assert_allclose(s.axes_manager[1].scale, 1.0, rtol=1e-5) assert s.metadata.General.date == "2016-06-13" assert s.metadata.General.time == "15:59:52" - assert s.metadata.General.FileIO.Number_0.hyperspy_version == hs_version + assert s.metadata.General.FileIO.Number_0.hyperspy_version == hs.__version__ assert s.metadata.General.FileIO.Number_0.io_plugin == "rsciio.tiff.api" @@ -741,7 +761,7 @@ def test_read_TVIPS_metadata(): "FileIO": { "0": { "operation": "load", - "hyperspy_version": hs_version, + "hyperspy_version": hs.__version__, "io_plugin": "rsciio.tiff.api", } }, diff --git a/rsciio/tests/test_tvips.py b/rsciio/tests/test_tvips.py index 291a62ac4..35fb17419 100644 --- a/rsciio/tests/test_tvips.py +++ b/rsciio/tests/test_tvips.py @@ -20,14 +20,18 @@ import gc import os import tempfile -import traits.api as traits from packaging import version as pversion import numpy as np import pytest import dask -import hyperspy.api as hs +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") + +import traits.api as t + +from hyperspy.misc.utils import DictionaryTreeBrowser + from rsciio.tvips.api import ( _guess_image_mode, _get_main_header_from_signal, @@ -40,7 +44,6 @@ file_writer, file_reader, ) -from hyperspy.misc.utils import DictionaryTreeBrowser from rsciio.utils.tools import dummy_context_manager @@ -171,7 +174,7 @@ def fake_signals(fake_signal_3D, fake_signal_4D, fake_signal_5D): ("1/m", 2), ("nm", 1), ("m", 1), - (traits.Undefined, None), + (t.Undefined, None), ("foo", None), ("", None), ("s", None), diff --git a/rsciio/tests/test_usid.py b/rsciio/tests/test_usid.py index 4be11bafa..f84ebf167 100644 --- a/rsciio/tests/test_usid.py +++ b/rsciio/tests/test_usid.py @@ -5,8 +5,7 @@ import numpy as np import pytest -from hyperspy import api as hs - +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") usid = pytest.importorskip("pyUSID", reason="pyUSID not installed") sidpy = pytest.importorskip("sidpy", reason="sidpy not installed") diff --git a/rsciio/tests/test_zspy.py b/rsciio/tests/test_zspy.py index abac646e3..a523099e7 100644 --- a/rsciio/tests/test_zspy.py +++ b/rsciio/tests/test_zspy.py @@ -16,15 +16,13 @@ # You should have received a copy of the GNU General Public License # along with RosettaSciIO. If not, see . -import numpy as np import logging import os -import pytest -from hyperspy._signals.signal1d import Signal1D -from hyperspy.io import load -from hyperspy.signal import BaseSignal +import numpy as np +import pytest +hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") # zarr (because of numcodecs) is only supported on x86_64 machines zarr = pytest.importorskip("zarr", reason="zarr not installed") @@ -33,7 +31,7 @@ class TestZspy: @pytest.fixture def signal(self): data = np.ones((10, 10, 10, 10)) - s = Signal1D(data) + s = hs.signals.Signal1D(data) return s @pytest.mark.parametrize("store_class", [zarr.N5Store, zarr.ZipStore]) @@ -48,7 +46,7 @@ def test_save_store(self, signal, tmp_path, store_class): assert os.path.isdir(filename) store2 = store_class(path=filename) - signal2 = load(store2) + signal2 = hs.load(store2) np.testing.assert_array_equal(signal2.data, signal.data) @@ -60,7 +58,7 @@ def test_save_ZipStore_close_file(self, signal, tmp_path): assert os.path.isfile(filename) store2 = zarr.ZipStore(path=filename) - s2 = load(store2) + s2 = hs.load(store2) np.testing.assert_array_equal(s2.data, signal.data) @@ -70,13 +68,13 @@ def test_save_wrong_store(self, signal, tmp_path, caplog): signal.save(store) store2 = zarr.N5Store(path=filename) - s2 = load(store2) + s2 = hs.load(store2) np.testing.assert_array_equal(s2.data, signal.data) store2 = zarr.NestedDirectoryStore(path=filename) with pytest.raises(BaseException): with caplog.at_level(logging.ERROR): - _ = load(store2) + _ = hs.load(store2) @pytest.mark.parametrize("overwrite", [None, True, False]) def test_overwrite(self, signal, overwrite, tmp_path): @@ -85,18 +83,18 @@ def test_overwrite(self, signal, overwrite, tmp_path): signal2 = signal * 2 signal2.save(filename=filename, overwrite=overwrite) if overwrite is None: - np.testing.assert_array_equal(signal.data, load(filename).data) + np.testing.assert_array_equal(signal.data, hs.load(filename).data) elif overwrite: - np.testing.assert_array_equal(signal2.data, load(filename).data) + np.testing.assert_array_equal(signal2.data, hs.load(filename).data) else: - np.testing.assert_array_equal(signal.data, load(filename).data) + np.testing.assert_array_equal(signal.data, hs.load(filename).data) def test_compression_opts(self, tmp_path): self.filename = tmp_path / "testfile.zspy" from numcodecs import Blosc comp = Blosc(cname="zstd", clevel=1, shuffle=Blosc.SHUFFLE) - BaseSignal([1, 2, 3]).save(self.filename, compressor=comp) + hs.signals.BaseSignal([1, 2, 3]).save(self.filename, compressor=comp) f = zarr.open(self.filename.__str__(), mode="r+") d = f["Experiments/__unnamed__/data"] assert d.compressor == comp @@ -107,11 +105,11 @@ def test_compression(self, compressor, tmp_path): from numcodecs import Blosc compressor = Blosc(cname="zstd", clevel=3, shuffle=Blosc.BITSHUFFLE) - s = Signal1D(np.ones((3, 3))) + s = hs.signals.Signal1D(np.ones((3, 3))) s.save( tmp_path / "test_compression.zspy", overwrite=True, compressor=compressor ) - load(tmp_path / "test_compression.zspy") + _ = hs.load(tmp_path / "test_compression.zspy") def test_non_valid_zspy(tmp_path, caplog): @@ -123,4 +121,4 @@ def test_non_valid_zspy(tmp_path, caplog): with pytest.raises(IOError): with caplog.at_level(logging.ERROR): - _ = load(filename) + _ = hs.load(filename) diff --git a/rsciio/utils/array.py b/rsciio/utils/array.py new file mode 100644 index 000000000..7135a9db9 --- /dev/null +++ b/rsciio/utils/array.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Copyright 2007-2022 The HyperSpy developers +# +# This file is part of RosettaSciIO. +# +# RosettaSciIO is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# RosettaSciIO is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with RosettaSciIO. If not, see . + +from packaging.version import Version + +import numpy as np + + +def get_numpy_kwargs(array): + """ + Convenience funtion to return a dictionary containing the `like` keyword + if numpy>=1.20. + + Note + ---- + `like` keyword is an experimental feature introduced in numpy 1.20 and is + pending on acceptance of NEP 35 + + """ + kw = {} + if Version(np.__version__) >= Version("1.20"): + kw["like"] = array + + return kw diff --git a/rsciio/utils/rgb_tools.py b/rsciio/utils/rgb_tools.py index 933f305b4..a1a31790a 100644 --- a/rsciio/utils/rgb_tools.py +++ b/rsciio/utils/rgb_tools.py @@ -19,7 +19,7 @@ import numpy as np from dask.array import Array -from hyperspy.misc.utils import get_numpy_kwargs +from rsciio.utils.array import get_numpy_kwargs rgba8 = np.dtype({"names": ["R", "G", "B", "A"], "formats": ["u1", "u1", "u1", "u1"]}) diff --git a/setup.py b/setup.py index df72c01de..ab14f2554 100644 --- a/setup.py +++ b/setup.py @@ -172,7 +172,7 @@ def run(self): "scalebar_export": ["matplotlib-scalebar", "matplotlib>=3.1.3"], "tiff": ["tifffile>=2020.2.16", "imagecodecs>=2020.1.31"], "usid": ["pyUSID"], - "zspy": ['zarr'], + "zspy": ["zarr"], "tests": [ "pytest>=3.6", "pytest-xdist", From 4b292b01502421301de740cb6352dee0d621ce15 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Tue, 16 Aug 2022 10:48:31 +0100 Subject: [PATCH 04/13] Remove unused class in emd plugin and remove traits dependency on emd plugin --- rsciio/emd/api.py | 424 +--------------------------------------------- 1 file changed, 7 insertions(+), 417 deletions(-) diff --git a/rsciio/emd/api.py b/rsciio/emd/api.py index 7c7f9b0e9..f2a1852cd 100644 --- a/rsciio/emd/api.py +++ b/rsciio/emd/api.py @@ -32,7 +32,6 @@ import warnings import math import logging -import traits.api as t import h5py import numpy as np @@ -51,413 +50,6 @@ _logger = logging.getLogger(__name__) -class EMD(object): - - """Class for storing electron microscopy datasets. - - The :class:`~.EMD` class can hold an arbitrary amount of datasets in the - `signals` dictionary. These are saved as HyperSpy - :class:`~hyperspy.signal.Signal` instances. Global metadata are saved in - four dictionaries (`user`, `microscope`, `sample`, `comments`). To print - relevant information about the EMD instance use the :func:`~.log_info` - function. EMD instances can be loaded from and saved to emd-files, an - hdf5 standard developed at Lawrence - Berkeley National Lab (https://emdatasets.com/). - - Attributes - ---------- - signals: dictionary - Dictionary which contains all datasets as - :class:`~hyperspy.signal.Signal` instances. - user : dictionary - Dictionary which contains user related metadata. - microscope : dictionary - Dictionary which contains microscope related metadata. - sample : dictionary - Dictionary which contains sample related metadata. - comments : dictionary - Dictionary which contains additional commentary metadata. - - """ - - _log = logging.getLogger(__name__) - - def __init__( - self, signals=None, user=None, microscope=None, sample=None, comments=None - ): - msg = ( - "Direct instantiation of the EMD class is deprecated and will be " - "removed in HyperSpy v2.0. Please use the `hs.load` function " - "instead." - ) - warnings.warn(msg, VisibleDeprecationWarning) - self._log.debug("Calling __init__") - # Create dictionaries if not present: - if signals is None: - signals = {} - if user is None: - user = {} - if microscope is None: - microscope = {} - if sample is None: - sample = {} - if comments is None: - comments = {} - # Make sure some default keys are present in user: - for key in ["name", "institution", "department", "email"]: - if key not in user: - user[key] = "" - self.user = user - # Make sure some default keys are present in microscope: - for key in ["name", "voltage"]: - if key not in microscope: - microscope[key] = "" - self.microscope = microscope - # Make sure some default keys are present in sample: - for key in ["material", "preparation"]: - if key not in sample: - sample[key] = "" - self.sample = sample - # Add comments: - self.comments = comments - # Make sure the signals are added properly to signals: - self.signals = {} - for name, signal in signals.items(): - self.add_signal(signal, name) - - def __getitem__(self, key): - # This is for accessing the raw data easily. For the signals use - # emd.signals[key]! - return self.signals[key].data - - def _write_signal_to_group(self, signal_group, signal): - self._log.debug("Calling _write_signal_to_group") - # Save data: - dataset = signal_group.require_group(signal.metadata.General.title) - maxshape = tuple(None for _ in signal.data.shape) - dataset.create_dataset("data", data=signal.data, chunks=True, maxshape=maxshape) - # Iterate over all dimensions: - for i in range(len(signal.data.shape)): - key = "dim{}".format(i + 1) - axis = signal.axes_manager._axes[i] - offset = axis.offset - scale = axis.scale - dim = dataset.create_dataset(key, data=[offset, offset + scale]) - name = axis.name - if name is None: - name = "" - dim.attrs["name"] = name - units = axis.units - if units is None: - units = "" - else: - units = "[{}]".format("_".join(list(units))) - dim.attrs["units"] = units - # Write metadata: - dataset.attrs["emd_group_type"] = 1 - for key, value in signal.metadata.Signal: - try: # If something h5py can't handle is saved in the metadata... - dataset.attrs[key] = value - except Exception: # ...let the user know what could not be added! - self._log.exception( - "The hdf5 writer could not write the following " - "information in the file: %s : %s", - key, - value, - ) - - def _read_signal_from_group(self, name, group, lazy=False): - self._log.debug("Calling _read_signal_from_group") - signal_dict = {} - # Extract essential data: - data = group.get("data") - if lazy: - data = da.from_array(data, chunks=data.chunks) - else: - data = np.asanyarray(data) - signal_dict["data"] = data - # Iterate over all dimensions: - # EMD does not have a standard way to describe the signal axis. - # Therefore we don't set the `navigate` attribute of the axes - axes = [] - for i in range(len(data.shape)): - axis_dict = {} - dim = group.get("dim{}".format(i + 1)) - axis_name = dim.attrs.get("name", "") - if isinstance(axis_name, bytes): - axis_name = axis_name.decode("utf-8") - - axis_units = dim.attrs.get("units", "") - if isinstance(axis_units, bytes): - axis_units = axis_units.decode("utf-8") - units = re.findall(r"[^_\W]+", axis_units) - try: - if len(dim) == 1: - scale = 1.0 - self._log.warning( - "Could not calculate scale of axis {}. " - "Setting scale to 1".format(i) - ) - else: - scale = dim[1] - dim[0] - offset = dim[0] - # HyperSpy then uses defaults (1.0 and 0.0)! - except (IndexError, TypeError) as e: - self._log.warning( - "Could not calculate scale/offset of " "axis {}: {}".format(i, e) - ) - axis_dict["scale"] = scale - axis_dict["offset"] = offset - axis_dict["units"] = units - axis_dict["name"] = name - axis_dict["_type"] = "UniformDataAxis" - axes.append(axis_dict) - # Extract metadata: - signal_dict["axes"] = axes - metadata = {} - for key, value in group.attrs.items(): - metadata[key] = value - metadata["General"]["user"] = self.user - metadata["General"]["microscope"] = self.microscope - metadata["General"]["sample"] = self.sample - metadata["General"]["comments"] = self.comments - signal_dict["metadata"] = metadata - if data.dtype == object: - self._log.warning( - "RosettaSciIO could not load the data in {}, " - "skipping it".format(name) - ) - else: - # Add signal: - self.signals[name] = signal_dict - - def add_signal(self, signal, name=None, metadata=None): - """Add a HyperSpy signal to the EMD instance and make sure all - metadata is present. - - Parameters - ---------- - signal : :class:`~hyperspy.signal.Signal` - HyperSpy signal which should be added to the EMD instance. - name : string, optional - Name of the (used as a key for the `signals` dictionary). If not - specified, `signal.metadata.General.title` will be used. If this - is an empty string, both name and signal title are set to 'dataset' - per default. If specified, `name` overwrites the - signal title. - metadata : dictionary - Dictionary which holds signal specific metadata which will - be added to the signal. - - Returns - ------- - None - - Notes - ----- - This is the preferred way to add signals to the EMD instance. - Directly adding to the `signals` dictionary is possible but does not - make sure all metadata are correct. This method is also called in - the standard constructor on all entries in the `signals` dictionary! - - """ - self._log.debug("Calling add_signal") - # Create metadata if not present: - if metadata is None: - metadata = {} - signal_md = {} - # Check and save title: - if name is None: # Overwrite Signal title! - # Take title of Signal! - if signal.metadata.General.title != "": - name = signal.metadata.General.title - else: # Take default! - name = "__unnamed__" - signal.metadata.General.title = name - # Save signal metadata: - signal.metadata.Signal.add_dictionary(metadata) - # Save global metadata: - signal.metadata.General.add_node("user") - signal.metadata.General.user.add_dictionary(self.user) - signal.metadata.General.add_node("microscope") - signal.metadata.General.microscope.add_dictionary(self.microscope) - signal.metadata.General.add_node("sample") - signal.metadata.General.sample.add_dictionary(self.sample) - signal.metadata.General.add_node("comments") - signal.metadata.General.comments.add_dictionary(self.comments) - # Also save metadata as original_metadata: - signal.original_metadata.add_dictionary(signal.metadata.as_dictionary()) - # Add signal: - self.signals[name] = signal - - @classmethod - def load_from_emd(cls, filename, lazy=False, dataset_name=None): - """Construct :class:`~.EMD` object from an emd-file. - - Parameters - ---------- - filename : str - The name of the emd-file from which to load the signals. Standard - file extesnion is '.emd'. - False : bool, optional - If False (default) loads data to memory. If True, enables loading - only if requested. - dataset_name : str or iterable, optional - Only add dataset with specific name. Note, this has to be the full - group path in the file. For example '/experimental/science_data'. - If the dataset is not found, an IOError with the possible - datasets will be raised. Several names can be specified - in the form of a list. - - Returns - ------- - emd : :class:`~.EMD` - A :class:`~.EMD` object containing the loaded signals. - - """ - cls._log.debug("Calling load_from_emd") - # Read in file: - emd_file = h5py.File(filename, "r") - # Creat empty EMD instance: - emd = cls() - # Extract user: - user_group = emd_file.get("user") - if user_group is not None: - for key, value in user_group.attrs.items(): - emd.user[key] = value - # Extract microscope: - microscope_group = emd_file.get("microscope") - if microscope_group is not None: - for key, value in microscope_group.attrs.items(): - emd.microscope[key] = value - # Extract sample: - sample_group = emd_file.get("sample") - if sample_group is not None: - for key, value in sample_group.attrs.items(): - emd.sample[key] = value - # Extract comments: - comments_group = emd_file.get("comments") - if comments_group is not None: - for key, value in comments_group.attrs.items(): - emd.comments[key] = value - # Extract signals: - node_list = list(emd_file.keys()) - for key in [ - "user", - "microscope", - "sample", - "comments", - ]: # Nodes which are not the data! - if key in node_list: - node_list.pop(node_list.index(key)) # Pop all unwanted nodes! - dataset_in_file_list = [] - for node in node_list: - data_group = emd_file.get(node) - if data_group is not None: - for group in data_group.values(): - name = group.name - if isinstance(group, h5py.Group): - if group.attrs.get("emd_group_type") == 1: - dataset_in_file_list.append(name) - if len(dataset_in_file_list) == 0: - raise IOError("No datasets found in {0}".format(filename)) - dataset_read_list = [] - if dataset_name is not None: - if isinstance(dataset_name, str): - dataset_name = [dataset_name] - - for temp_dataset_name in dataset_name: - if temp_dataset_name in dataset_in_file_list: - dataset_read_list.append(temp_dataset_name) - else: - raise IOError( - "Dataset with name {0} not found in the file. " - "Possible datasets are {1}.".format( - temp_dataset_name, ", ".join(dataset_in_file_list) - ) - ) - else: - dataset_read_list = dataset_in_file_list - for dataset_read in dataset_read_list: - group = emd_file[dataset_read] - emd._read_signal_from_group(dataset_read, group, lazy) - - # Close file and return EMD object: - if not lazy: - emd_file.close() - return emd - - def save_to_emd(self, filename="datacollection.emd"): - """Save :class:`~.EMD` data in a file with emd(hdf5)-format. - - Parameters - ---------- - filename : string, optional - The name of the emd-file in which to store the signals. - The default is 'datacollection.emd'. - - Returns - ------- - None - - """ - self._log.debug("Calling save_to_emd") - # Open file: - emd_file = h5py.File(filename, "w") - # Write version: - ver_maj, ver_min = EMD_VERSION.split(".") - emd_file.attrs["version_major"] = ver_maj - emd_file.attrs["version_minor"] = ver_min - # Write user: - user_group = emd_file.require_group("user") - for key, value in self.user.items(): - user_group.attrs[key] = value - # Write microscope: - microscope_group = emd_file.require_group("microscope") - for key, value in self.microscope.items(): - microscope_group.attrs[key] = value - # Write sample: - sample_group = emd_file.require_group("sample") - for key, value in self.sample.items(): - sample_group.attrs[key] = value - # Write comments: - comments_group = emd_file.require_group("comments") - for key, value in self.comments.items(): - comments_group.attrs[key] = value - # Write signals: - signal_group = emd_file.require_group("signals") - for signal in self.signals.values(): - self._write_signal_to_group(signal_group, signal) - # Close file and return EMD object: - emd_file.close() - - def log_info(self): - """( all relevant information about the EMD instance.""" - self._log.debug("Calling log_info") - pad_string0 = "-------------------------\n" - pad_string1 = "\n-------------------------\n" - info_str = "\nUser:" + pad_string1 - for key, value in self.user.items(): - info_str += "{:<15}: {}\n".format(key, value) - info_str += pad_string0 + "\nMicroscope:" + pad_string1 - for key, value in self.microscope.items(): - info_str += "{:<15}: {}\n".format(key, value) - info_str += pad_string0 + "\nSample:" + pad_string1 - for key, value in self.sample.items(): - info_str += "{:<15}: {}\n".format(key, value) - info_str += pad_string0 + "\nComments:" + pad_string1 - for key, value in self.comments.items(): - info_str += "{:<15}: {}\n".format(key, value) - info_str += pad_string0 + "\nData:" + pad_string1 - for key, value in self.signals.items(): - info_str += "{:<15}: {}\n".format(key, value) - sig_dict = value.metadata.Signal - for k in sig_dict.keys(): - info_str += " |-- {}: {}\n".format(k, sig_dict[k]) - info_str += pad_string0 - self._log.info(info_str) - - class EMD_NCEM: """Class for reading and writing the Berkeley variant of the electron @@ -674,7 +266,7 @@ def _read_data_from_groups( shape = data.shape if len(array_list) > 1: - offset, scale, units = 0, 1, t.Undefined + offset, scale, units = 0, 1, None if self._is_prismatic_file and "depth" in stack_key: simu_om = original_metadata.get("simulation_parameters", {}) if "numSlices" in simu_om.keys(): @@ -699,11 +291,11 @@ def _read_data_from_groups( ) # When non-uniform/non-linear axis are implemented, adjust # the final depth to the "total_thickness" - offset, scale, units = 0, 1, t.Undefined + offset, scale, units = 0, 1, None axes.append( { "index_in_array": 0, - "name": stack_key if stack_key is not None else t.Undefined, + "name": stack_key if stack_key is not None else None, "offset": offset, "scale": scale, "size": len(array_list), @@ -751,9 +343,7 @@ def _read_data_from_groups( def _parse_attribute(self, obj, key): value = obj.attrs.get(key) - if value is None: - value = t.Undefined - else: + if value is not None: if not isinstance(value, str): value = value.decode() if key == "units": @@ -1367,7 +957,7 @@ def _parse_frame_time(self, original_metadata, factor=1): frame_time = original_metadata["Scan"]["FrameTime"] time_unit = "s" except KeyError: - frame_time, time_unit = None, t.Undefined + frame_time, time_unit = None, None frame_time, time_unit = self._convert_scale_units(frame_time, time_unit, factor) return frame_time, time_unit @@ -1575,10 +1165,10 @@ def _get_dispersion_offset(self, original_metadata): return dispersion, offset, "keV" except KeyError: _logger.warning("The spectrum calibration can't be loaded.") - return 1, 0, t.Undefined + return 1, 0, None def _convert_scale_units(self, value, units, factor=1): - if units == t.Undefined: + if units is None: return value, units factor /= 2 v = float(value) * _UREG(units) From 9eca0fe7e462e243083e689b36a58d04cc94ca74 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Tue, 16 Aug 2022 11:34:58 +0100 Subject: [PATCH 05/13] Remove marker no_hyperspy --- .github/workflows/tests.yml | 12 ++---------- pyproject.toml | 3 --- rsciio/tests/test_image.py | 18 ++++++++++++------ rsciio/tests/test_import.py | 22 +--------------------- rsciio/tvips/api.py | 13 ++++++++----- 5 files changed, 23 insertions(+), 45 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1258b1085..17f911cc4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -46,8 +46,7 @@ jobs: - name: Set Environment Variable shell: bash - # Set PIP_SELECTOR and PYTEST_ARGS environment variable - # depending on matrix.LABEL + # Set PIP_SELECTOR environment variable according to matrix.LABEL run: | if [[ -n "${{ matrix.LABEL }}" && "${{ matrix.LABEL }}" == *"minimum"* ]]; then PIP_SELECTOR="[tests]" @@ -56,13 +55,6 @@ jobs: fi echo "PIP_SELECTOR=${PIP_SELECTOR}" >> $GITHUB_ENV - if [[ -n "${{ matrix.LABEL }}" && "${{ matrix.LABEL }}" == *"wo-hyperspy"* ]]; then - PYTEST_ARGS="--pyargs rsciio.tests.test_import -m no_hyperspy" - else - PYTEST_ARGS="--pyargs rsciio --reruns 3 -n 2 --cov=. --cov-report=xml" - fi - echo "PYTEST_ARGS=${PYTEST_ARGS}" >> $GITHUB_ENV - - name: Display version run: | python --version @@ -90,7 +82,7 @@ jobs: - name: Run test suite run: | - pytest ${{ env.PYTEST_ARGS }} + pytest --pyargs rsciio --reruns 3 -n 2 --cov=. --cov-report=xml - name: Upload coverage to Codecov if: ${{ always() }} diff --git a/pyproject.toml b/pyproject.toml index 6e8de4dba..ffeabae8d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,9 +10,6 @@ minversion = "6.0" testpaths = [ "rsciio/tests", ] -markers = [ - "no_hyperspy: marks tests to run without hyperspy", -] [tool.towncrier] package = "rsciio" diff --git a/rsciio/tests/test_image.py b/rsciio/tests/test_image.py index 5f731f4e7..2e907bcd9 100644 --- a/rsciio/tests/test_image.py +++ b/rsciio/tests/test_image.py @@ -19,17 +19,13 @@ import numpy as np import pytest -try: - import hyperspy.api as hs -except: - pass - from rsciio.image.api import file_writer @pytest.mark.parametrize(("dtype"), ["uint8", "uint32"]) @pytest.mark.parametrize(("ext"), ["png", "bmp", "gif", "jpg"]) def test_save_load_cycle_grayscale(dtype, ext, tmp_path): + hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") s = hs.signals.Signal2D(np.arange(128 * 128).reshape(128, 128).astype(dtype)) print("Saving-loading cycle for the extension:", ext) @@ -41,6 +37,7 @@ def test_save_load_cycle_grayscale(dtype, ext, tmp_path): @pytest.mark.parametrize(("color"), ["rgb8", "rgba8", "rgb16", "rgba16"]) @pytest.mark.parametrize(("ext"), ["png", "bmp", "gif", "jpeg"]) def test_save_load_cycle_color(color, ext, tmp_path): + hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") dim = 4 if "rgba" in color else 3 dtype = "uint8" if "8" in color else "uint16" if dim == 4 and ext == "jpeg": @@ -61,6 +58,7 @@ def test_save_load_cycle_color(color, ext, tmp_path): @pytest.mark.parametrize(("dtype"), ["uint8", "uint32"]) @pytest.mark.parametrize(("ext"), ["png", "bmp", "gif", "jpg"]) def test_save_load_cycle_kwds(dtype, ext, tmp_path): + hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") s = hs.signals.Signal2D(np.arange(128 * 128).reshape(128, 128).astype(dtype)) print("Saving-loading cycle for the extension:", ext) @@ -82,6 +80,7 @@ def test_save_load_cycle_kwds(dtype, ext, tmp_path): @pytest.mark.parametrize(("ext"), ["png", "bmp", "gif", "jpg"]) def test_export_scalebar(ext, tmp_path): + hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") pytest.importorskip("matplotlib_scalebar") data = np.arange(1e6).reshape((1000, 1000)) s = hs.signals.Signal2D(data) @@ -102,6 +101,7 @@ def test_export_scalebar(ext, tmp_path): def test_export_scalebar_reciprocal(tmp_path): + hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") pixels = 512 s = hs.signals.Signal2D(np.arange(pixels**2).reshape((pixels, pixels))) for axis in s.axes_manager.signal_axes: @@ -115,6 +115,7 @@ def test_export_scalebar_reciprocal(tmp_path): def test_export_scalebar_undefined_units(tmp_path): + hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") pixels = 512 s = hs.signals.Signal2D(np.arange(pixels**2).reshape((pixels, pixels))) @@ -125,6 +126,7 @@ def test_export_scalebar_undefined_units(tmp_path): def test_non_uniform(tmp_path): + hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") pixels = 16 s = hs.signals.Signal2D(np.arange(pixels**2).reshape((pixels, pixels))) s.axes_manager[0].convert_to_non_uniform_axis() @@ -135,6 +137,7 @@ def test_non_uniform(tmp_path): def test_export_scalebar_different_scale_units(tmp_path): + hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") pytest.importorskip("matplotlib_scalebar") pixels = 16 s = hs.signals.Signal2D(np.arange(pixels**2).reshape((pixels, pixels))) @@ -154,6 +157,7 @@ def test_export_scalebar_different_scale_units(tmp_path): @pytest.mark.parametrize("output_size", (512, [512, 512])) def test_export_output_size(output_size, tmp_path): + hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") pixels = 16 s = hs.signals.Signal2D(np.arange(pixels**2).reshape((pixels, pixels))) @@ -165,6 +169,7 @@ def test_export_output_size(output_size, tmp_path): @pytest.mark.parametrize("output_size", (512, (512, 512))) def test_export_output_size_non_square(output_size, tmp_path): + hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") pixels = (8, 16) s = hs.signals.Signal2D(np.arange(np.multiply(*pixels)).reshape(pixels)) @@ -181,6 +186,7 @@ def test_export_output_size_non_square(output_size, tmp_path): @pytest.mark.parametrize("output_size", (None, 512)) @pytest.mark.parametrize("aspect", (1, 0.5)) def test_export_output_size_aspect(aspect, output_size, tmp_path): + hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") pixels = (256, 256) s = hs.signals.Signal2D(np.arange(np.multiply(*pixels)).reshape(pixels)) @@ -196,6 +202,7 @@ def test_export_output_size_aspect(aspect, output_size, tmp_path): def test_save_image_navigation(tmp_path): + hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") pixels = 16 s = hs.signals.Signal2D(np.arange(pixels**2).reshape((pixels, pixels))) @@ -203,7 +210,6 @@ def test_save_image_navigation(tmp_path): s.T.save(fname, scalebar=True) -@pytest.mark.no_hyperspy def test_error_library_no_installed(tmp_path): axis = { "_type": "UniformDataAxis", diff --git a/rsciio/tests/test_import.py b/rsciio/tests/test_import.py index 760b2c490..0d0ce9f1b 100644 --- a/rsciio/tests/test_import.py +++ b/rsciio/tests/test_import.py @@ -18,32 +18,11 @@ import importlib -import pytest - -@pytest.mark.no_hyperspy def test_import_version(): from rsciio import __version__ -@pytest.mark.no_hyperspy -def test_import_with_minimal_dependencies_no_hyperspy(): - from rsciio import IO_PLUGINS - - for plugin in IO_PLUGINS: - if plugin["format_name"] not in [ - "Blockfile", - "Electron Microscopy Data (EMD)", - "MRCZ", - "Phenom Element Identification (ELID)", - "TIFF", - "TVIPS", - "USID", - "ZSpy", - ]: - importlib.import_module(plugin["api"]) - - def test_import_all(): from rsciio import IO_PLUGINS @@ -64,6 +43,7 @@ def test_import_all(): import tifffile except: plugin_name_to_remove.append("TIFF") + plugin_name_to_remove.append("Phenom Element Identification (ELID)") try: import pyUSID diff --git a/rsciio/tvips/api.py b/rsciio/tvips/api.py index 57ed9db10..5df5fb4fc 100644 --- a/rsciio/tvips/api.py +++ b/rsciio/tvips/api.py @@ -26,13 +26,12 @@ import numpy as np import dask.array as da import dask -import pint from dask.diagnostics import ProgressBar +import pint from numba import njit from rsciio.utils.tools import DTBox, sarray2dict from rsciio.utils.tools import dummy_context_manager -from hyperspy.defaults_parser import preferences from rsciio.utils.tools import _UREG @@ -607,9 +606,13 @@ def file_writer(filename, signal, **kwds): file_memmap["rotidx"] = rotator + 1 data = fdata[current_frame : current_frame + frames_saved] if signal["attributes"]["_lazy"]: - show_progressbar = kwds.get( - "show_progressbar", preferences.General.show_progressbar - ) + try: + from hyperspy.defaults_parser import preferences + + hs_show_progressbar = preferences.General.show_progressbar + except: + hs_show_progressbar = None + show_progressbar = kwds.get("show_progressbar", hs_show_progressbar) cm = ProgressBar if show_progressbar else dummy_context_manager with cm(): data.store(file_memmap["data"]) From 46f4cd365ffa951a3259e23de58390c7c18b5cb8 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Tue, 16 Aug 2022 11:28:18 +0100 Subject: [PATCH 06/13] Fix empad data packaging and fix release file on windows --- rsciio/tests/empad_data/scan_x4_y4.raw | Bin 1064960 -> 0 bytes rsciio/tests/test_empad.py | 9 +++++++-- setup.py | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) delete mode 100644 rsciio/tests/empad_data/scan_x4_y4.raw diff --git a/rsciio/tests/empad_data/scan_x4_y4.raw b/rsciio/tests/empad_data/scan_x4_y4.raw deleted file mode 100644 index 220ca33ded1d961ab036d09e17443b11ee813bfe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1064960 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

Ms+yV5mZM~9Yu9C)iG4ZQXNNi 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

nc8eVAxr4f}zQW{xl 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 diff --git a/rsciio/tests/test_empad.py b/rsciio/tests/test_empad.py index 09f59a658..9451070fd 100644 --- a/rsciio/tests/test_empad.py +++ b/rsciio/tests/test_empad.py @@ -20,6 +20,7 @@ import numpy as np import pytest +import gc hs = pytest.importorskip("hyperspy.api", reason="hyperspy not installed") @@ -39,12 +40,15 @@ def _create_raw_data(filename, shape): data.tofile(filename) -def setup_module(): +def setup_module(module): _create_raw_data(FILENAME_STACK_RAW, (166400,)) _create_raw_data(FILENAME_MAP_RAW, (4 * 4 * 130 * 128)) -def teardown_module(): +def teardown_module(module): + # run garbage collection to release file on windows + gc.collect() + fs = [f for f in [FILENAME_STACK_RAW, FILENAME_MAP_RAW] if os.path.exists(f)] for f in fs: @@ -77,6 +81,7 @@ def test_read_stack(lazy): assert s.metadata.General.date == "2019-06-07" assert s.metadata.General.time == "13:17:22.590279" assert s.metadata.Signal.signal_type == "electron_diffraction" + del s @pytest.mark.parametrize("lazy", (False, True)) diff --git a/setup.py b/setup.py index ab14f2554..6549041ac 100644 --- a/setup.py +++ b/setup.py @@ -368,6 +368,7 @@ def run(self): "tests/protochips_data/*.npy", "tests/protochips_data/*.csv", "tests/nexus_files/*.nxs", + "tests/empad_data/*.xml", ] }, # Although 'package_data' is the preferred approach, in some case you may From 7cb8b4246e1f8aebe7441c413c9770a81e4fde82 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Tue, 16 Aug 2022 11:49:34 +0100 Subject: [PATCH 07/13] Define `__all__` and `__dir__` in root `__init__.py` --- rsciio/__init__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rsciio/__init__.py b/rsciio/__init__.py index 9f436f212..146fa307d 100644 --- a/rsciio/__init__.py +++ b/rsciio/__init__.py @@ -34,3 +34,13 @@ specs = yaml.safe_load(stream) specs["api"] = "rsciio.%s.api" % os.path.split(sub)[1] IO_PLUGINS.append(specs) + + +__all__ = [ + "__version__", + "IO_PLUGINS", +] + + +def __dir__(): + return sorted(__all__) From 9850f5696eb3dba935e7513204e05cc277e9862f Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Tue, 16 Aug 2022 12:13:33 +0100 Subject: [PATCH 08/13] Add changelog note --- upcoming_changes/13.maintenance.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 upcoming_changes/13.maintenance.rst diff --git a/upcoming_changes/13.maintenance.rst b/upcoming_changes/13.maintenance.rst new file mode 100644 index 000000000..35f0f6ec6 --- /dev/null +++ b/upcoming_changes/13.maintenance.rst @@ -0,0 +1 @@ +Fix minimum install, add corresponding tests build and tidy up leftover code \ No newline at end of file From a1fdb7df30ea4c41db509c6a91be319a72a1a479 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Tue, 16 Aug 2022 18:28:50 +0100 Subject: [PATCH 09/13] Include `specifications.yaml` and missing test files in dist/wheel --- .gitignore | 1 + MANIFEST.in | 2 +- setup.py | 9 ++++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index e72950fd1..1d32961ba 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /docs/_build/* /build/* +/dist/* /RosettaSciIO.egg-info/* *__pycache__* *test_compilers.obj diff --git a/MANIFEST.in b/MANIFEST.in index 8b142ce14..ad03ec35e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,6 @@ include *.txt include *.rst -recursive-include rsciio *.pyx +recursive-include rsciio *.pyx *specifications.yaml recursive-include docs *.txt *.rst *.pdf *py *bat makefile include rsciio/tests/bruker_data/test_compilers.c diff --git a/setup.py b/setup.py index 6549041ac..b9f56c44a 100644 --- a/setup.py +++ b/setup.py @@ -185,9 +185,7 @@ def run(self): # Don't include "tests" and "docs" requirements since "all" is designed to be # used for user installation. runtime_extras_require = { - x: extras_require[x] - for x in extras_require.keys() - if x not in ["tests", "coverage", "build-doc"] + x: extras_require[x] for x in extras_require.keys() if x not in ["tests", "docs"] } extras_require["all"] = list(itertools.chain(*list(runtime_extras_require.values()))) @@ -324,6 +322,7 @@ def run(self): # MANIFEST.in as well. package_data={ "rsciio": [ + "*/specifications.yaml", "tests/blockfile_data/*.blo", "tests/dens_data/*.dens", "tests/dm_stackbuilder_plugin/test_stackbuilder_imagestack.dm3", @@ -363,6 +362,10 @@ def run(self): "tests/bruker_data/*.spx", "tests/ripple_files/*.rpl", "tests/ripple_files/*.raw", + "tests/panta_rhei_files/*.prz", + "tests/phenom_data/*.elid", + "tests/sur_data/*.sur", + "tests/sur_data/*.pro", "tests/emd_files/*.emd", "tests/emd_files/fei_emd_files.zip", "tests/protochips_data/*.npy", From b8cd0f193c73495f1295c33c11456591a867f449 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Tue, 16 Aug 2022 18:42:32 +0100 Subject: [PATCH 10/13] Add build CI workflow to check packaging --- .github/workflows/build.yml | 51 +++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..de7ce7bf6 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,51 @@ +name: Build + +on: [push, pull_request] + +jobs: + build-and-test: + name: Build + runs-on: ubuntu-latest + env: + PYTHON_VERSION: '3.10' + + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-python@v3 + name: Install Python + with: + python-version: '3.10' + + - name: Display version + run: | + python --version + pip --version + + - name: Install pypa/build + run: | + pip install build + + - name: Build a binary wheel and a source tarball + run: | + python -m build + + - name: Display content dist folder + run: | + ls dist/ + + - uses: actions/upload-artifact@v3 + with: + path: ./dist/* + + - name: Install distribution + run: | + pip install --pre --find-links dist rosettasciio[all,tests] + + - name: Install HyperSpy (dev) + run: | + pip install https://github.com/hyperspy/hyperspy/archive/refs/heads/RELEASE_next_major.zip + + - name: Test distribution + run: | + pytest --pyargs rsciio --reruns 3 -n 2 From 8f34d536a27a8f26a2533d4c6ff5bfb8647b7c90 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Tue, 16 Aug 2022 19:37:36 +0100 Subject: [PATCH 11/13] Improve coverage --- pyproject.toml | 7 +++++-- rsciio/tests/test_import.py | 6 ++++++ rsciio/tvips/api.py | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ffeabae8d..4048457a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta:__legacy__" addopts = "-ra -n auto --dist loadfile" minversion = "6.0" testpaths = [ - "rsciio/tests", + "rsciio/tests", ] [tool.towncrier] @@ -62,7 +62,10 @@ testpaths = "rsciio/tests/" [tool.coverage.run] branch = true source = ["rsciio"] -omit = ["rsciio/tests/*"] +omit = [ + "rsciio/tests/*", + "setup.py", +] [tool.coverage.report] precision = 2 diff --git a/rsciio/tests/test_import.py b/rsciio/tests/test_import.py index 0d0ce9f1b..9740fd20e 100644 --- a/rsciio/tests/test_import.py +++ b/rsciio/tests/test_import.py @@ -23,6 +23,12 @@ def test_import_version(): from rsciio import __version__ +def test_rsciio_dir(): + import rsciio + + assert dir(rsciio) == ["IO_PLUGINS", "__version__"] + + def test_import_all(): from rsciio import IO_PLUGINS diff --git a/rsciio/tvips/api.py b/rsciio/tvips/api.py index 5df5fb4fc..78b734338 100644 --- a/rsciio/tvips/api.py +++ b/rsciio/tvips/api.py @@ -610,7 +610,7 @@ def file_writer(filename, signal, **kwds): from hyperspy.defaults_parser import preferences hs_show_progressbar = preferences.General.show_progressbar - except: + except: # pragma: no cover hs_show_progressbar = None show_progressbar = kwds.get("show_progressbar", hs_show_progressbar) cm = ProgressBar if show_progressbar else dummy_context_manager From f75bc36e9e3ebdd05c0584a8b01093f6e548676e Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Sat, 20 Aug 2022 17:21:45 +0100 Subject: [PATCH 12/13] Tweak `MANIFEST.in` --- MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index ad03ec35e..af2cfe3ec 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,6 @@ include *.txt include *.rst recursive-include rsciio *.pyx *specifications.yaml -recursive-include docs *.txt *.rst *.pdf *py *bat makefile +recursive-include docs *.txt *.rst *.pdf *.py *.bat makefile include rsciio/tests/bruker_data/test_compilers.c From 784f1bd3094c6fc65934eb131a701ff960393fa8 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Sat, 20 Aug 2022 17:45:48 +0100 Subject: [PATCH 13/13] Check if hyperspy >=2.0 is installed to run the test suite --- rsciio/conftest.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 rsciio/conftest.py diff --git a/rsciio/conftest.py b/rsciio/conftest.py new file mode 100644 index 000000000..025b6c054 --- /dev/null +++ b/rsciio/conftest.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2007-2022 The HyperSpy developers +# +# This file is part of RosettaSciIO. +# +# RosettaSciIO is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# RosettaSciIO is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with RosettaSciIO. If not, see . + +from packaging.version import Version + +try: + import hyperspy + + if Version(hyperspy.__version__) < Version("2.0.dev"): + raise Exception( + "To run the test suite using hyperspy, \ + hyperspy 2.0 or higher is required." + ) +except ImportError: + pass