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 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c3b8f74c8..17f911cc4 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,35 @@ jobs: with: python-version: ${{ matrix.PYTHON_VERSION }} + - name: Set Environment Variable + shell: bash + # Set PIP_SELECTOR environment variable according to 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 + - 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 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..af2cfe3ec 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,6 @@ include *.txt include *.rst -recursive-include rsciio *.pyx -recursive-include docs *.txt *.rst *.pdf *py *bat makefile +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/pyproject.toml b/pyproject.toml index 182919c60..4048457a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,12 +3,12 @@ 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", + "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/__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__) 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 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/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) 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/empad_data/scan_x4_y4.raw b/rsciio/tests/empad_data/scan_x4_y4.raw deleted file mode 100644 index 220ca33de..000000000 Binary files a/rsciio/tests/empad_data/scan_x4_y4.raw and /dev/null differ 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..9451070fd 100644 --- a/rsciio/tests/test_empad.py +++ b/rsciio/tests/test_empad.py @@ -20,9 +20,12 @@ import numpy as np import pytest +import gc + +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 @@ -37,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: @@ -75,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/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 b35d9981a..2e907bcd9 100644 --- a/rsciio/tests/test_image.py +++ b/rsciio/tests/test_image.py @@ -19,20 +19,13 @@ import numpy as np import pytest -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 +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) @@ -44,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": @@ -64,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) @@ -85,13 +80,15 @@ 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) 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): @@ -104,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: @@ -117,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))) @@ -127,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() @@ -136,10 +136,9 @@ 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): + 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))) s.axes_manager[0].scale = 2 @@ -158,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))) @@ -169,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)) @@ -185,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)) @@ -200,8 +202,36 @@ 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))) fname = tmp_path / "test_save_image_navigation.jpg" s.T.save(fname, scalebar=True) + + +def test_error_library_no_installed(tmp_path): + 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 + except: + # When matplotlib is not installed, raises an error to inform user + # that matplotlib is necessary + with pytest.raises(ValueError): + file_writer(tmp_path / "test_image_error.jpg", signal_dict, output_size=64) + + with pytest.raises(ValueError): + 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 new file mode 100644 index 000000000..9740fd20e --- /dev/null +++ b/rsciio/tests/test_import.py @@ -0,0 +1,72 @@ +# -*- 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 + + +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 + + 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") + plugin_name_to_remove.append("Phenom Element Identification (ELID)") + + 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/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/tvips/api.py b/rsciio/tvips/api.py index 57ed9db10..78b734338 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: # 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 with cm(): data.store(file_memmap["data"]) 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/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..b9f56c44a 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,12 @@ 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", "pytest-xdist", @@ -181,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()))) @@ -320,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", @@ -359,11 +362,16 @@ 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", "tests/protochips_data/*.csv", "tests/nexus_files/*.nxs", + "tests/empad_data/*.xml", ] }, # Although 'package_data' is the preferred approach, in some case you may 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