Skip to content

Commit

Permalink
Merge branch 'main' into subloops
Browse files Browse the repository at this point in the history
  • Loading branch information
tlambert03 authored Feb 21, 2024
2 parents f4ad51d + 8b2fd66 commit f01d3fc
Show file tree
Hide file tree
Showing 25 changed files with 88 additions and 204 deletions.
27 changes: 10 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,17 @@ jobs:
fail-fast: false
matrix:
platform: [macos-latest, windows-latest, "ubuntu-latest"]
python-version: ["3.9", "3.10", "3.11"]
include:
- python-version: "3.7"
platform: "ubuntu-latest"
- python-version: "3.8"
platform: "ubuntu-latest"
- python-version: "3.8"
platform: "windows-latest"
- python-version: "3.12-dev"
platform: "ubuntu-latest"
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- uses: actions/cache@v3
- uses: actions/cache@v4
id: cache
with:
path: tests/data
Expand All @@ -69,17 +60,19 @@ jobs:
run: pytest -v --cov=nd2 --cov-report=xml --cov-report=term

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}

benchmarks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"

- uses: actions/cache@v3
- uses: actions/cache@v4
id: cache
with:
path: tests/data
Expand All @@ -95,7 +88,7 @@ jobs:
run: python -m pip install .[test]

- name: Run benchmarks
uses: CodSpeedHQ/action@v1
uses: CodSpeedHQ/action@v2
with:
run: pytest --codspeed -v --color=yes

Expand All @@ -108,7 +101,7 @@ jobs:
with:
fetch-depth: 0

- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: "3.x"

Expand Down
6 changes: 2 additions & 4 deletions .github/workflows/cron.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ jobs:
python-version: ['3.9', '3.10', '3.11']
platform: [ubuntu-latest, macos-latest, windows-latest]
include:
- python-version: "3.7"
platform: "ubuntu-latest"
- python-version: "3.8"
platform: "ubuntu-latest"
- python-version: "3.8"
Expand All @@ -30,11 +28,11 @@ jobs:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- uses: actions/cache@v3
- uses: actions/cache@v4
id: cache
with:
path: tests/data
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x

Expand Down
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,23 @@ repos:
- id: trailing-whitespace

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.4
rev: v0.2.0
hooks:
- id: ruff
args: [--fix]

- repo: https://github.com/psf/black
rev: 23.10.1
rev: 24.1.1
hooks:
- id: black

- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.15
rev: v0.16
hooks:
- id: validate-pyproject

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.6.1
rev: v1.8.0
hooks:
- id: mypy
files: "^src/"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

`.nd2` (Nikon NIS Elements) file reader.

This reader provides a pure python implementation the official Nikon ND2 SDK.
This reader provides a pure python implementation of the Nikon ND2 SDK.

> It _used_ to wrap the official SDK with Cython, but has since been completely
> rewritten to be pure python (for performance, ease of distribution, and
Expand Down Expand Up @@ -73,7 +73,7 @@ import numpy as np
my_array = nd2.imread('some_file.nd2') # read to numpy array
my_array = nd2.imread('some_file.nd2', dask=True) # read to dask array
my_array = nd2.imread('some_file.nd2', xarray=True) # read to xarray
my_array = nd2.imread('some_file.nd2', xarray=True, dask=True) # read file to dask-xarray
my_array = nd2.imread('some_file.nd2', xarray=True, dask=True) # read to dask-xarray

# or open a file with nd2.ND2File
f = nd2.ND2File('some_file.nd2')
Expand Down
10 changes: 3 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ build-backend = "hatchling.build"
name = "nd2"
description = "Yet another nd2 (Nikon NIS Elements) file reader"
readme = "README.md"
requires-python = ">=3.7"
requires-python = ">=3.8"
license = { text = "BSD 3-Clause License" }
authors = [{ email = "[email protected]", name = "Talley Lambert" }]
classifiers = [
"Development Status :: 4 - Beta",
"License :: OSI Approved :: BSD License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
Expand All @@ -30,7 +29,7 @@ test = [
"aicsimageio; python_version < '3.12'",
"dask[array]",
"imagecodecs",
"lxml",
"lxml; python_version >= '3.9'",
"numpy >=1.26; python_version >= '3.12'",
"numpy; python_version < '3.12'",
"ome-types",
Expand Down Expand Up @@ -69,17 +68,14 @@ documentation = "https://tlambert03.github.io/nd2/"
[tool.hatch.version]
source = "vcs"

[tool.hatch.build.hooks.vcs]
version-file = "src/nd2/_version.py"

[tool.hatch.build.targets.wheel]
only-include = ["src"]
sources = ["src"]

# https://beta.ruff.rs/docs/rules/
[tool.ruff]
line-length = 88
target-version = "py37"
target-version = "py38"
src = ["src/nd2", "tests"]
select = [
"E", # style errors
Expand Down
1 change: 1 addition & 0 deletions scripts/gather.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""gather metadata from all files in test/data with all nd readers."""

import contextlib
import json
from pathlib import Path
Expand Down
1 change: 1 addition & 0 deletions scripts/nd2_describe.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
python scripts/nd2_describe.py > tests/samples_metadata.json
"""

import struct
from dataclasses import asdict
from pathlib import Path
Expand Down
7 changes: 5 additions & 2 deletions src/nd2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
"""nd2: A Python library for reading and writing ND2 files."""

from importlib.metadata import PackageNotFoundError, version

try:
from ._version import version as __version__
except ImportError:
__version__ = version(__name__)
except PackageNotFoundError: # pragma: no cover
__version__ = "unknown"

__author__ = "Talley Lambert"
__email__ = "[email protected]"
__all__ = [
Expand Down
7 changes: 3 additions & 4 deletions src/nd2/_binary.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Utilities for binary layers in ND2 files."""

from __future__ import annotations

import io
Expand Down Expand Up @@ -131,12 +132,10 @@ def __init__(self, data: list[BinaryLayer]) -> None:
self._data = data

@overload
def __getitem__(self, key: int) -> BinaryLayer:
...
def __getitem__(self, key: int) -> BinaryLayer: ...

@overload
def __getitem__(self, key: slice) -> list[BinaryLayer]:
...
def __getitem__(self, key: slice) -> list[BinaryLayer]: ...

def __getitem__(self, key: int | slice) -> BinaryLayer | list[BinaryLayer]:
return self._data[key]
Expand Down
1 change: 1 addition & 0 deletions src/nd2/_parse/_chunk_decode.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""FIXME: this has a lot of code duplication with _chunkmap.py."""

from __future__ import annotations

import mmap
Expand Down
1 change: 1 addition & 0 deletions src/nd2/_parse/_legacy_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
all of this logic is duplicated in _clx_xml.py.
_legacy.py just needs some slight updates to deal with different parsing results.
"""

from __future__ import annotations

import re
Expand Down
5 changes: 3 additions & 2 deletions src/nd2/_parse/_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ def load_metadata(raw_meta: RawMetaDict, global_meta: GlobalMetadata) -> strct.M
if matrix and (matrix.get("Columns") == 2 and matrix.get("Rows") == 2):
# matrix["Data"] is a list of int64, we need to recast to float
data = bytearray(matrix["Data"])
matrix_data: tuple[float, float, float, float] = tuple( # type: ignore
matrix_data: tuple[float, float, float, float] = tuple(
i[0] for i in strctd.iter_unpack(data)
)
volume["cameraTransformationMatrix"] = matrix_data
Expand Down Expand Up @@ -637,7 +637,8 @@ def load_metadata(raw_meta: RawMetaDict, global_meta: GlobalMetadata) -> strct.M
channel=channel_meta,
loops=loops,
microscope=strct.Microscope(
**microscope, modalityFlags=flags # type: ignore
**microscope,
modalityFlags=flags, # type: ignore
),
volume=strct.Volume(
**volume,
Expand Down
7 changes: 5 additions & 2 deletions src/nd2/_sdk_types.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
"""Various raw dict structures likely to be found in an ND2 file."""

from __future__ import annotations

from enum import IntEnum, auto
from typing import TYPE_CHECKING, Union
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing_extensions import Literal, NotRequired, TypeAlias, TypedDict
from typing import Literal, TypedDict, Union

from typing_extensions import NotRequired, TypeAlias

class RawAttributesDict(TypedDict, total=False):
uiWidth: int
Expand Down
22 changes: 1 addition & 21 deletions src/nd2/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,14 @@

import math
import re
import warnings
from datetime import datetime, timezone
from itertools import product
from typing import TYPE_CHECKING, BinaryIO, NamedTuple, cast

if TYPE_CHECKING:
from os import PathLike
from typing import Any, Callable, ClassVar, Mapping, Sequence, Union
from typing import Any, Callable, ClassVar, Final, Mapping, Sequence, Union

from typing_extensions import Final

from nd2.readers import ND2Reader
from nd2.structures import ExpLoop

StrOrPath = Union[str, PathLike]
Expand Down Expand Up @@ -77,19 +73,6 @@ def is_legacy(path: StrOrPath) -> bool:
return fh.read(4) == OLD_HEADER_MAGIC


def get_reader(
path: str, validate_frames: bool = False, search_window: int = 100
) -> ND2Reader: # pragma: no cover
warnings.warn(
"Deprecated, use nd2.readers.ND2Reader.create if you want to "
"directly instantiate a reader subclass.",
stacklevel=2,
)
from nd2.readers import ND2Reader

return ND2Reader.create(path, search_window * 1000 if validate_frames else None)


def is_new_format(path: str) -> bool:
# TODO: this is just for dealing with missing test data
with open(path, "rb") as fh:
Expand Down Expand Up @@ -159,9 +142,6 @@ def parse_time(time_str: str) -> datetime:
raise ValueError(f"Could not parse {time_str}") # pragma: no cover


# utils for converting records to dicts, in recorded_data method


def convert_records_to_dict_of_lists(
records: ListOfDicts, null_val: Any = float("nan")
) -> DictOfLists:
Expand Down
4 changes: 1 addition & 3 deletions src/nd2/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime
from pathlib import Path
from typing import Any, Iterable, Iterator, Sequence, cast, no_type_check

from typing_extensions import TypedDict
from typing import Any, Iterable, Iterator, Sequence, TypedDict, cast, no_type_check

import nd2

Expand Down
Loading

0 comments on commit f01d3fc

Please sign in to comment.