diff --git a/.copier-answers.ess.yml b/.copier-answers.ess.yml index c0b54ae9..d7d7e3b8 100644 --- a/.copier-answers.ess.yml +++ b/.copier-answers.ess.yml @@ -1,3 +1,3 @@ # Changes here will be overwritten by Copier; NEVER EDIT MANUALLY -_commit: 847e5e4 +_commit: 0951a4b _src_path: https://github.com/scipp/ess_template diff --git a/.copier-answers.yml b/.copier-answers.yml index 33be7caf..e9f997f3 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier; NEVER EDIT MANUALLY -_commit: afbe5c7 +_commit: 6848c57 _src_path: gh:scipp/copier_template description: Diffraction data reduction for the European Spallation Source max_python: '3.12' diff --git a/.github/ISSUE_TEMPLATE/blank.md b/.github/ISSUE_TEMPLATE/blank.md index 2fb131c1..22a75aeb 100644 --- a/.github/ISSUE_TEMPLATE/blank.md +++ b/.github/ISSUE_TEMPLATE/blank.md @@ -1,6 +1,6 @@ --- -name: blank -about: A blank issue template +name: Blank +about: General issue that does not fit another category title: '' labels: '' assignees: '' diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 7e5a7bc6..98aaf568 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -65,7 +65,7 @@ jobs: name: docs_html path: html/ - - uses: JamesIves/github-pages-deploy-action@v4.6.0 + - uses: JamesIves/github-pages-deploy-action@v4.6.1 if: ${{ inputs.publish }} with: branch: gh-pages diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 508073fe..4442b1b9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: args: [ "--drop-empty-cells", "--extra-keys 'metadata.language_info.version cell.metadata.jp-MarkdownHeadingCollapsed cell.metadata.pycharm'" ] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.1 + rev: v0.4.3 hooks: - id: ruff args: [ --fix ] diff --git a/conda/meta.yaml b/conda/meta.yaml index 073e59d1..39a7a305 100644 --- a/conda/meta.yaml +++ b/conda/meta.yaml @@ -18,8 +18,9 @@ requirements: run: - python>=3.10 + {# Conda does not allow spaces between package name and version, so remove them #} {% for package in dependencies %} - - {% if package == "graphviz" %}python-graphviz{% else %}{{ package }}{% endif %} + - {% if package == "graphviz" %}python-graphviz{% else %}{{ package|replace(" ", "") }}{% endif %} {% endfor %} diff --git a/docs/_templates/doc_version.html b/docs/_templates/doc_version.html index 48f9aacf..35ee3b05 100644 --- a/docs/_templates/doc_version.html +++ b/docs/_templates/doc_version.html @@ -1,2 +1,2 @@ -Current {{ project }} version: {{ version }} (older versions). +Current ESSdiffraction version: {{ version }} (older versions). diff --git a/docs/conf.py b/docs/conf.py index 92e52d92..288770a4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,12 +1,15 @@ -# -*- coding: utf-8 -*- - import doctest import os import sys +from importlib.metadata import PackageNotFoundError from importlib.metadata import version as get_version +from sphinx.util import logging + sys.path.insert(0, os.path.abspath(".")) +logger = logging.getLogger(__name__) + # General information about the project. project = "ESSdiffraction" copyright = "2024 Scipp contributors" @@ -35,6 +38,8 @@ import sciline.sphinxext.domain_types # noqa: F401 extensions.append("sciline.sphinxext.domain_types") + # See https://github.com/tox-dev/sphinx-autodoc-typehints/issues/457 + suppress_warnings = ["config.cache"] except ModuleNotFoundError: pass @@ -111,9 +116,15 @@ # |version| and |release|, also used in various other places throughout the # built documents. # - -release = get_version("essdiffraction") -version = ".".join(release.split(".")[:3]) # CalVer +try: + release = get_version("essdiffraction") + version = ".".join(release.split('.')[:3]) # CalVer +except PackageNotFoundError: + logger.info( + "Warning: determining version from package metadata failed, falling back to " + "a dummy version number." + ) + release = version = "0.0.0-dev" warning_is_error = True diff --git a/pyproject.toml b/pyproject.toml index 63c82a58..83cbb454 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,7 +77,7 @@ extend-exclude = [ [tool.ruff.lint] # See https://docs.astral.sh/ruff/rules/ -select = ["B", "C4", "DTZ", "E", "F", "G", "I", "PERF", "PGH", "PT", "PYI", "RUF", "S", "T20", "W"] +select = ["B", "C4", "DTZ", "E", "F", "G", "I", "PERF", "PGH", "PT", "PYI", "RUF", "S", "T20", "UP", "W"] ignore = [ # Conflict with ruff format, see # https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules diff --git a/requirements/make_base.py b/requirements/make_base.py index 1e1f48e3..68a17e84 100644 --- a/requirements/make_base.py +++ b/requirements/make_base.py @@ -1,7 +1,6 @@ import sys from argparse import ArgumentParser from pathlib import Path -from typing import List import tomli @@ -20,7 +19,7 @@ """ -def write_dependencies(dependency_name: str, dependencies: List[str]) -> None: +def write_dependencies(dependency_name: str, dependencies: list[str]) -> None: path = Path(f"{dependency_name}.in") if path.exists(): sections = path.read_text().split(CUSTOM_AUTO_SEPARATOR) diff --git a/src/ess/dream/instrument_view.py b/src/ess/dream/instrument_view.py index 0c7c529e..58f5e0f9 100644 --- a/src/ess/dream/instrument_view.py +++ b/src/ess/dream/instrument_view.py @@ -3,7 +3,7 @@ from __future__ import annotations from html import escape -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any import plopp as pp import scipp as sc @@ -16,9 +16,9 @@ def instrument_view( - data: Union[sc.DataArray, sc.DataGroup, dict], - dim: Optional[str] = None, - pixel_size: Optional[Union[float, sc.Variable]] = None, + data: sc.DataArray | sc.DataGroup | dict, + dim: str | None = None, + pixel_size: float | sc.Variable | None = None, **kwargs: Any, ) -> Box: """ @@ -48,7 +48,7 @@ def instrument_view( return Box(view.children) -def _to_data_group(data: Union[sc.DataArray, sc.DataGroup, dict]) -> sc.DataGroup: +def _to_data_group(data: sc.DataArray | sc.DataGroup | dict) -> sc.DataGroup: if isinstance(data, sc.DataArray): data = sc.DataGroup({data.name or "data": data}) elif isinstance(data, dict): @@ -71,9 +71,9 @@ class InstrumentView: def __init__( self, - data: Union[sc.DataArray, sc.DataGroup, dict], - dim: Optional[str] = None, - pixel_size: Optional[Union[float, sc.Variable]] = None, + data: sc.DataArray | sc.DataGroup | dict, + dim: str | None = None, + pixel_size: float | sc.Variable | None = None, **kwargs, ): from plopp.widgets import SliceWidget, slice_dims diff --git a/src/ess/dream/io/geant4.py b/src/ess/dream/io/geant4.py index 50fb896b..d5060e4a 100644 --- a/src/ess/dream/io/geant4.py +++ b/src/ess/dream/io/geant4.py @@ -1,8 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright (c) 2023 Scipp contributors (https://github.com/scipp) -from typing import Dict, Optional - import numpy as np import sciline import scipp as sc @@ -96,7 +94,7 @@ def _adjust_coords(da: sc.DataArray) -> None: ) -def _group(detectors: Dict[str, sc.DataArray]) -> Dict[str, sc.DataGroup]: +def _group(detectors: dict[str, sc.DataArray]) -> dict[str, sc.DataGroup]: elements = ("module", "segment", "counter", "wire", "strip") def group(key: str, da: sc.DataArray) -> sc.DataArray: @@ -114,7 +112,7 @@ def group(key: str, da: sc.DataArray) -> sc.DataArray: def _split_detectors( data: sc.DataArray, detector_id_name: str = "det ID" -) -> Dict[str, sc.DataArray]: +) -> dict[str, sc.DataArray]: groups = data.group( sc.concat( [ @@ -162,7 +160,7 @@ def _split_detectors( def _extract_detector( detector_groups: sc.DataArray, detector_id_name: str, detector_id: sc.Variable -) -> Optional[sc.DataArray]: +) -> sc.DataArray | None: events = detector_groups[detector_id_name, detector_id].value if len(events) == 0: return None @@ -191,10 +189,10 @@ def patch_detector_data( def geant4_detector_dimensions( data: RawDetectorData[SampleRun], -) -> NeXusDetectorDimensions[NeXusDetectorName]: +) -> NeXusDetectorDimensions: # For geant4 data, we group by detector identifier, so the data already has # logical dimensions, so we simply return the dimensions of the detector. - return NeXusDetectorDimensions[NeXusDetectorName](data.sizes) + return NeXusDetectorDimensions(data.sizes) def geant4_load_calibration( diff --git a/src/ess/powder/correction.py b/src/ess/powder/correction.py index 8e8fc4dd..38049bbe 100644 --- a/src/ess/powder/correction.py +++ b/src/ess/powder/correction.py @@ -2,7 +2,7 @@ # Copyright (c) 2023 Scipp contributors (https://github.com/scipp) """Correction algorithms for powder diffraction.""" -from typing import Any, Dict, Optional +from typing import Any import scipp as sc from scippneutron.conversion.graph import beamline, tof @@ -30,8 +30,8 @@ def normalize_by_monitor( data: sc.DataArray, *, monitor: sc.DataArray, - wavelength_edges: Optional[sc.Variable] = None, - smooth_args: Optional[Dict[str, Any]] = None, + wavelength_edges: sc.Variable | None = None, + smooth_args: dict[str, Any] | None = None, ) -> sc.DataArray: """ Normalize event data by a monitor. diff --git a/src/ess/powder/masking.py b/src/ess/powder/masking.py index 1e5305b3..1a4655d3 100644 --- a/src/ess/powder/masking.py +++ b/src/ess/powder/masking.py @@ -4,7 +4,7 @@ Masking functions for the powder workflow. """ -from typing import Iterable +from collections.abc import Iterable import numpy as np import sciline diff --git a/src/ess/powder/smoothing.py b/src/ess/powder/smoothing.py index c1cd242d..4df44e7d 100644 --- a/src/ess/powder/smoothing.py +++ b/src/ess/powder/smoothing.py @@ -4,8 +4,6 @@ Smoothing arrays data. """ -from typing import Optional - import scipp as sc from scipp.scipy.signal import butter @@ -29,7 +27,7 @@ def _ensure_no_variances(var: sc.DataArray) -> sc.DataArray: def lowpass( - da: sc.DataArray, *, dim: str, N: int, Wn: sc.Variable, coord: Optional[str] = None + da: sc.DataArray, *, dim: str, N: int, Wn: sc.Variable, coord: str | None = None ) -> sc.DataArray: """ Smooth data using a lowpass frequency filter. diff --git a/src/ess/powder/types.py b/src/ess/powder/types.py index 93998698..e4006c5b 100644 --- a/src/ess/powder/types.py +++ b/src/ess/powder/types.py @@ -7,8 +7,9 @@ pipeline. """ +from collections.abc import Callable from enum import Enum -from typing import Any, Callable, Dict, NewType, TypeVar +from typing import Any, NewType, TypeVar import sciline import scipp as sc @@ -89,10 +90,8 @@ class DataWithScatteringCoordinates(sciline.Scope[RunType, sc.DataArray], sc.Dat d-spacing.""" -class NeXusDetectorDimensions( - sciline.Scope[NeXusDetectorName, Dict[str, int]], Dict[str, int] -): - """Logical detector dimensions.""" +NeXusDetectorDimensions = NewType("NeXusDetectorDimensions", dict[str, int]) +"""Logical detector dimensions.""" class DspacingData(sciline.Scope[RunType, sc.DataArray], sc.DataArray): @@ -139,7 +138,7 @@ class MaskedData(sciline.Scope[RunType, sc.DataArray], sc.DataArray): dspacing regions.""" -MaskedDetectorIDs = NewType("MaskedDetectorIDs", Dict[str, sc.Variable]) +MaskedDetectorIDs = NewType("MaskedDetectorIDs", dict[str, sc.Variable]) """1-D variable listing all masked detector IDs.""" diff --git a/src/ess/snspowder/powgen/beamline.py b/src/ess/snspowder/powgen/beamline.py index 7bd82dba..2b30ade9 100644 --- a/src/ess/snspowder/powgen/beamline.py +++ b/src/ess/snspowder/powgen/beamline.py @@ -55,11 +55,9 @@ def map_detector_to_spectrum( def powgen_detector_dimensions( detector_name: NeXusDetectorName, -) -> NeXusDetectorDimensions[NeXusDetectorName]: +) -> NeXusDetectorDimensions: """Dimensions used by POWGEN detectors.""" - return NeXusDetectorDimensions[NeXusDetectorName]( - DETECTOR_BANK_SIZES[detector_name] - ) + return NeXusDetectorDimensions(DETECTOR_BANK_SIZES[detector_name]) providers = (powgen_detector_dimensions,) diff --git a/src/ess/snspowder/powgen/calibration.py b/src/ess/snspowder/powgen/calibration.py index 6e2a47e3..82fa10f0 100644 --- a/src/ess/snspowder/powgen/calibration.py +++ b/src/ess/snspowder/powgen/calibration.py @@ -9,7 +9,6 @@ """ from pathlib import Path -from typing import Dict, Optional, Union import numpy as np import scipp as sc @@ -28,11 +27,11 @@ def _as_boolean_mask(var: sc.Variable) -> sc.Variable: def _parse_calibration_instrument_args( - filename: Union[str, Path], + filename: str | Path, *, - instrument_filename: Optional[str] = None, - instrument_name: Optional[str] = None, -) -> Dict[str, str]: + instrument_filename: str | None = None, + instrument_name: str | None = None, +) -> dict[str, str]: if instrument_filename is not None: if instrument_name is not None: raise ValueError( @@ -57,11 +56,11 @@ def _parse_calibration_instrument_args( def load_calibration( - filename: Union[str, Path], + filename: str | Path, *, - instrument_filename: Optional[str] = None, - instrument_name: Optional[str] = None, - mantid_args: Optional[dict] = None, + instrument_filename: str | None = None, + instrument_name: str | None = None, + mantid_args: dict | None = None, ) -> sc.Dataset: """ Load and return calibration data. diff --git a/src/ess/snspowder/powgen/data.py b/src/ess/snspowder/powgen/data.py index aea6e744..0ce636a0 100644 --- a/src/ess/snspowder/powgen/data.py +++ b/src/ess/snspowder/powgen/data.py @@ -11,7 +11,6 @@ CalibrationFilename, Filename, NeXusDetectorDimensions, - NeXusDetectorName, ProtonCharge, RawDataAndMetadata, ReducibleDetectorData, @@ -104,7 +103,7 @@ def pooch_load(filename: Filename[RunType]) -> RawDataAndMetadata[RunType]: def pooch_load_calibration( filename: CalibrationFilename, - detector_dimensions: NeXusDetectorDimensions[NeXusDetectorName], + detector_dimensions: NeXusDetectorDimensions, ) -> CalibrationData: """Load the calibration data for the POWGEN test data.""" if filename is None: @@ -120,7 +119,7 @@ def pooch_load_calibration( def extract_raw_data( - dg: RawDataAndMetadata[RunType], sizes: NeXusDetectorDimensions[NeXusDetectorName] + dg: RawDataAndMetadata[RunType], sizes: NeXusDetectorDimensions ) -> ReducibleDetectorData[RunType]: """Return the events from a loaded data group.""" # Remove the tof binning and dimension, as it is not needed and it gets in the way diff --git a/src/ess/snspowder/powgen/instrument_view.py b/src/ess/snspowder/powgen/instrument_view.py index 15002c59..677c04f0 100644 --- a/src/ess/snspowder/powgen/instrument_view.py +++ b/src/ess/snspowder/powgen/instrument_view.py @@ -1,6 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright (c) 2023 Scipp contributors (https://github.com/scipp) -from typing import Optional import scipp as sc import scippneutron as scn @@ -9,8 +8,8 @@ def instrument_view( da: sc.DataArray, positions: str = "position", - pixel_size: Optional[float] = None, - components: Optional[dict] = None, + pixel_size: float | None = None, + components: dict | None = None, **kwargs, ): """ diff --git a/tests/dream/io/geant4_test.py b/tests/dream/io/geant4_test.py index b2162a16..74522663 100644 --- a/tests/dream/io/geant4_test.py +++ b/tests/dream/io/geant4_test.py @@ -3,7 +3,6 @@ import zipfile from io import BytesIO -from typing import Optional, Set import numpy as np import pytest @@ -49,9 +48,7 @@ def file_without_sans(load_file_without_sans): return BytesIO(load_file_without_sans) -def assert_index_coord( - coord: sc.Variable, *, values: Optional[Set[int]] = None -) -> None: +def assert_index_coord(coord: sc.Variable, *, values: set[int] | None = None) -> None: assert coord.ndim == 1 assert coord.unit is None assert coord.dtype == "int64" diff --git a/tests/powder/filtering_test.py b/tests/powder/filtering_test.py index 3c4b9604..95661cae 100644 --- a/tests/powder/filtering_test.py +++ b/tests/powder/filtering_test.py @@ -2,8 +2,6 @@ # Copyright (c) 2023 Scipp contributors (https://github.com/scipp) # @author Jan-Lukas Wynen -from typing import Tuple - import numpy as np import scipp as sc @@ -58,7 +56,7 @@ def test_make_data_with_pulse_time(): def make_data_with_pulse_time_and_proton_charge( rng, n_event, n_proton_charge, bad_charge, bad_charge_indices -) -> Tuple[sc.DataArray, sc.DataArray]: +) -> tuple[sc.DataArray, sc.DataArray]: data = make_data_with_pulse_time(rng, n_event) start_time = data.bins.coords['pulse_time'].min()