Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ jobs:
- run: pipx run check-manifest

test:
name: Test ${{ matrix.os }} py${{ matrix.python-version }} ${{ matrix.min }}
name: Test ${{ matrix.os }} py${{ matrix.python-version }} ${{ matrix.min }} ${{ matrix.resolution }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.12", "3.13", "3.14"]
min: [""]
resolution: ["highest"]
exclude:
# tensorstore has no clean cp314 Windows wheel: the first one (0.1.79)
# and everything >=0.1.77 crash at interpreter shutdown on Windows
Expand All @@ -41,6 +41,16 @@ jobs:
- os: ubuntu-latest
python-version: "3.12"
min: "minimal"
# test the lowest dependency versions we claim to support
- os: ubuntu-latest
python-version: "3.12"
resolution: "lowest-direct"
- os: ubuntu-latest
python-version: "3.13"
resolution: "lowest-direct"
- os: ubuntu-latest
python-version: "3.14"
resolution: "lowest-direct"

env:
UV_PYTHON: ${{ matrix.python-version }}
Expand All @@ -54,13 +64,13 @@ jobs:
- if: ${{ matrix.min == 'minimal' }}
run: uv sync --no-dev --group test
- if: ${{ matrix.min != 'minimal' }}
run: uv sync --no-dev --group test --all-extras
run: uv sync --no-dev --group test --all-extras --resolution ${{ matrix.resolution }}

- run: uv run coverage run -p -m pytest --color=yes -v

- uses: actions/upload-artifact@v7
with:
name: covreport-${{ matrix.os }}-py${{ matrix.python-version }}-${{ matrix.min }}
name: covreport-${{ matrix.os }}-py${{ matrix.python-version }}-${{ matrix.min }}-${{ matrix.resolution }}
path: ./.coverage*
include-hidden-files: true

Expand Down
44 changes: 30 additions & 14 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ classifiers = [
]
dependencies = [
"annotated-types >=0.7.0",
# min pins per-python reflect the first release shipping a wheel for that
# interpreter (newer pythons need newer compiled deps).
# min pins per-python reflect the first release shipping a wheel
"numpy >=2.3.2; python_version >= '3.14'",
"numpy >=2.1.0; python_version >= '3.13'",
"numpy >=2.0",
"pint >=0.23",
"pint >=0.24.4",
"platformdirs >=4.3.6",
"pydantic >=2.12; python_version >= '3.14'",
# pydantic 2.12.0/.1 mis-build some models under py3.14 (deferred annotations).
"pydantic >=2.12.2; python_version >= '3.14'",
"pydantic >=2.8",
"fpbase",
"fpbase >=0.1.2",
"pydantic-settings >2.5.0",
"scipy >=1.16.1; python_version >= '3.14'",
"scipy >=1.15.2",
Expand All @@ -52,8 +52,9 @@ dependencies = [
"tensorstore >=0.1.79; python_version >= '3.14'",
"tensorstore >=0.1.76",
"tqdm >=4.67.1",
"xarray >=2024.1.0",
"zarr >=2.17,<3.0",
"xarray >=2025.7.0; python_version >= '3.14'",
"xarray >=2025.1.1",
"zarr >=3",
]

[project.urls]
Expand All @@ -64,22 +65,30 @@ repository = "https://github.com/tlambert03/microsim"
[project.optional-dependencies]
view = [
"ndv[pyqt,vispy]",
"matplotlib>=3.10.5; python_version >= '3.14'",
"matplotlib>=3.10.1",
# matplotlib <3.10.7 calls pyparsing's deprecated `oneOf` (warns with
# pyparsing >=3.3).
"matplotlib>=3.10.7",
# optional OpenGL speedup; no cp314 wheel and fails to build from source
"pyopengl-accelerate>=3.1.9; python_version < '3.14'",
]
io = ["tifffile>=2025.2.18", "imageio[ffmpeg]>=2.22"]
cosem = [
"dask>=2024.1.0",
"imageio>=2.22",
"boto3>=1.32",
"supabase>=2.13.0",
# supabase <2.17 bundles the deprecated `gotrue` (warns at import; renamed
# to supabase_auth in 2.17).
"supabase>=2.17.0",
"s3fs>=0.4.2",
"xarray-datatree>=0.0.14",
]
torch = ["torch>=2.6.0", "torchaudio>=2.7.0"]
jax = ["jax[cpu]>=0.5.2"]
torch = [
# torch/torchaudio only ship cp314 wheels from 2.9.0.
"torch>=2.9.0; python_version >= '3.14'",
"torchaudio>=2.9.0; python_version >= '3.14'",
"torch>=2.6.0",
"torchaudio>=2.7.0",
]
# jaxlib only ships cp314 wheels from 0.7.1 (jax/jaxlib versions are coupled).
jax = ["jax[cpu]>=0.7.1; python_version >= '3.14'", "jax[cpu]>=0.5.2"]
all = ["microsim[view,io,cosem]", "rich>=13"]

[dependency-groups]
Expand Down Expand Up @@ -194,6 +203,13 @@ filterwarnings = [
"ignore::pytest.PytestUnraisableExceptionWarning",
# supabase>=2.31 passes now-deprecated params (timeout/verify/proxy) to postgrest
"ignore:The '.*' parameter is deprecated:DeprecationWarning",
# zarr v3 (esp. 3.0.x) warns that the string-coord dtype / vlen-utf8 codec
# used for channel names isn't in the v3 spec yet; intentional and benign.
"ignore:The data type .* does not have a Zarr V3 specification:FutureWarning",
"ignore:The \\w+ .* is currently not part in the Zarr format 3 specification:UserWarning",
# numcodecs >=0.16.4 (pulled in with older zarr 3.x) deprecates its bundled
# crc32c at import time; harmless and outside our control.
"ignore:crc32c usage is deprecated:DeprecationWarning",
]

# https://coverage.readthedocs.io/en/6.4/config.html
Expand Down
6 changes: 4 additions & 2 deletions src/microsim/_data_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def __mul__(self, other: Any) -> ArrayProtocol: ...


def from_cache(path: Path, xp: NumpyAPI | None = None) -> xrDataArray:
data_set = xarray.open_zarr(path)
data_set = xarray.open_zarr(path, consolidated=False)
# get the first data variable
first_da = next(iter(data_set.data_vars))
# xarray.open_zarr uses dask by default. we may want that eventually
Expand All @@ -85,7 +85,9 @@ def to_cache(da: xrDataArray, path: Path, dtype: npt.DTypeLike | None = None) ->
# coerce to a contiguous numpy array: numcodecs calls np.array(..., copy=False),
# which raises on numpy>=2 for non-contiguous or non-numpy (e.g. jax) buffers.
da.data = np.ascontiguousarray(da.data)
da.to_zarr(path, mode="w")
# consolidated metadata is not part of the zarr v3 spec (zarr emits a warning);
# skip it so reads/writes stay spec-compliant across zarr 2 and 3.
da.to_zarr(path, mode="w", consolidated=False)


def _serializable_attrs(attrs: Any) -> Any:
Expand Down
196 changes: 0 additions & 196 deletions src/microsim/cosem/_xarray.py

This file was deleted.

11 changes: 0 additions & 11 deletions src/microsim/cosem/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@

if TYPE_CHECKING:
import numpy as np
import xarray as xr
from datatree import DataTree
from tensorstore import TensorStore

# ------------------------ MODELS ------------------------
Expand Down Expand Up @@ -172,15 +170,6 @@ def read(
bin_mode=_bin_mode,
)

def read_xarray(self) -> "xr.DataArray | DataTree":
"""Read image as xarray or DataTree.

This is less tested and used than `read`. Let me know if you need it.
"""
from microsim.cosem._xarray import read_xarray

return read_xarray(self.url)

@property
def attrs(self) -> dict[str, Any]:
if not getattr(self, "_attrs", None):
Expand Down
4 changes: 3 additions & 1 deletion src/microsim/schema/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,9 @@ def _write(self, result: xr.DataArray) -> None:
result.attrs = {"microsim.Simulation": sim_data}
result.coords[Axis.C] = [c.name for c in result.coords[Axis.C].values]
if self.output_path.suffix == ".zarr":
result.to_zarr(self.output_path, mode="w")
# consolidated metadata is not part of the zarr v3 spec (zarr warns);
# skip it so reads/writes stay spec-compliant across zarr 2 and 3.
result.to_zarr(self.output_path, mode="w", consolidated=False)
elif self.output_path.suffix in (".nc",):
result.to_netcdf(self.output_path)
elif self.output_path.suffix in (".tif", ".tiff"):
Expand Down
Loading
Loading