Skip to content
Open
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
43 changes: 43 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11"]

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Needed for hatch-vcs to determine version

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
version: "latest"

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

- name: Install dependencies
run: uv sync --all-groups

- name: Run tests with pytest
run: uv run pytest -v --cov=xarray_ome --cov-report=xml --cov-report=term

- name: Upload coverage to Codecov
if: matrix.python-version == '3.11'
uses: codecov/codecov-action@v5
with:
file: ./coverage.xml
fail_ci_if_error: false
62 changes: 62 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# TODO List

## High Priority

### Zarr Backend Fallback

Currently, when `xr.open_dataset(..., engine="ome-zarr")` is called on a regular (non-OME-NGFF) zarr file, it will raise an error. We should detect this case and automatically fall back to xarray's native zarr backend.

**Implementation notes:**

- The backend's `open_dataset()` and `open_datatree()` already check `_detect_store_type()`
- They try to fall back when `store_type == "unknown"`
- However, the fallback currently calls `open_ome_dataset()` which also checks and raises ValueError
- Need to either:
1. Catch ValueError in backend and retry with zarr engine
2. Pass a flag to `open_ome_dataset()` to skip the check
3. Restructure so backend does fallback before calling `open_ome_dataset()`

**Related code:**

- `xarray_ome/backend.py`: Backend entry point with fallback logic
- `xarray_ome/reader.py`: `open_ome_dataset()` and `open_ome_datatree()` with detection
- `xarray_ome/_store_utils.py`: `_detect_store_type()` function

## Medium Priority

### Add working code example at docs homepage start

The docs homepage should have a concrete working example right at the start that users can copy-paste and run immediately.

### HCS Plate Structure Support

Add support for High Content Screening (HCS) plate/well structures from OME-NGFF.

**References:**

- <https://ngff.openmicroscopy.org/latest/#hcs-layout>

### Performance Optimizations

- Benchmark and optimize coordinate transformation
- Consider caching metadata parsing
- Profile large file opening

### Integration with Visualization Tools

- Examples with matplotlib/napari
- Helper functions for common viz patterns

## Low Priority

### Additional Metadata Validation Options

- More granular validation controls
- Custom validation rules
- Better error messages for invalid metadata

### Time Label Support

Infrastructure is ready in `transforms_to_coords()` with `time_labels` parameter, but OME-NGFF spec doesn't currently define standard time labels location (unlike channel labels in `omero.channels[].label`).

Wait for spec extension before implementing.
93 changes: 66 additions & 27 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,59 +245,98 @@ write_ome_datatree(dt, "modified.ome.zarr")

## Metadata Attributes

### DataTree Attributes
### Overview

When using `open_ome_datatree()`, the root node contains:
OME-NGFF metadata is broken out into separate, readable attributes for easy access. The complete metadata dict is also preserved for round-tripping.

- **ome_ngff_metadata** : `dict`
### Common Attributes (DataTree and Dataset)

Complete OME-NGFF metadata including:
- `axes`: Axis definitions (name, type, unit)
- `datasets`: Dataset paths and coordinate transformations
- `version`: OME-NGFF specification version
- `name`: Image name
- Additional metadata fields
These attributes are present in both DataTree root nodes and Datasets:

### Dataset Attributes
- **ome_name** : `str`

Each Dataset (from `open_ome_dataset()` or DataTree child nodes) contains:
Image name from OME-NGFF metadata.
Example: `'image'`

- **ome_scale** : `dict[str, float]`
- **ome_version** : `str`

Scale factors for each dimension. Maps dimension names to scale values.
Example: `{'c': 1.0, 'z': 0.5, 'y': 0.36, 'x': 0.36}`
OME-NGFF specification version.
Example: `'0.4'`

- **ome_translation** : `dict[str, float]`
- **ome_axes** : `list[str]`

Translation offsets for each dimension. Maps dimension names to offset values.
Example: `{'c': 0.0, 'z': 0.0, 'y': 0.0, 'x': 0.0}`
Axis names in order.
Example: `['c', 'z', 'y', 'x']`

- **ome_axes_types** : `list[str | None]`

- **ome_axes_units** : `dict[str, str | None]`
Axis types (e.g., 'channel', 'space', 'time').
Example: `['channel', 'space', 'space', 'space']`

Physical units for each dimension.
Example: `{'c': None, 'z': 'micrometer', 'y': 'micrometer', 'x': 'micrometer'}`
- **ome_axes_units** : `dict[str, str]` (optional)

Physical units for axes that have them.
Example: `{'z': 'micrometer', 'y': 'micrometer', 'x': 'micrometer'}`

- **ome_axes_orientations** : `dict[str, str]` (optional)

Anatomical orientation for spatial axes (if RFC-4 metadata present).

- **ome_ngff_resolution** : `int`
- **ome_num_resolutions** : `int`

The resolution level index (only in Datasets from `open_ome_dataset()`).
Number of resolution levels in the multiscale pyramid.
Example: `3`

- **ome_multiscale_paths** : `list[str]`

Paths to each resolution level.
Example: `['0', '1', '2']`

- **ome_channels** : `list[str]` (optional)

Channel labels from `omero.channels[].label`.
Example: `['LaminB1', 'Dapi']`

- **ome_channel_colors** : `list[str]` (optional)

Channel colors (hex RGB) from `omero.channels[].color`.
Example: `['0000FF', 'FFFF00']`

- **ome_channel_windows** : `list[dict]` (optional)

Rendering window settings for each channel from `omero.channels[].window`.
Example: `[{'min': 0.0, 'max': 65535.0, 'start': 0.0, 'end': 1500.0}, ...]`

- **ome_ngff_metadata** : `dict`

Full OME-NGFF metadata (only in Datasets from `open_ome_dataset()`).
Complete OME-NGFF metadata for round-tripping. Contains all metadata
fields in their original nested structure.

### Dataset-Only Attributes

Datasets also contain coordinate transformation information:

- **ome_scale** : `dict[str, float]`

Scale factors for each dimension. Maps dimension names to scale values.
Example: `{'c': 1.0, 'z': 0.5, 'y': 0.36, 'x': 0.36}`

- **ome_translation** : `dict[str, float]`

Translation offsets for each dimension. Maps dimension names to offset values.
Example: `{'c': 0.0, 'z': 0.0, 'y': 0.0, 'x': 0.0}`

- **ome_ngff_resolution** : `int`

The resolution level index (only in Datasets from `open_ome_dataset()`).

- **ome_image_name** : `str` (optional)

Image name from OME-NGFF metadata, if present.
Image name from OME-NGFF metadata (duplicates `ome_name` for backward compatibility).

- **ome_channel_labels** : `list[str]` (optional)

Channel labels extracted from `omero.channels[].label` metadata.
Used as coordinate values for the channel dimension when available.
Example: `['LaminB1', 'Dapi']`
Channel labels (duplicates `ome_channels` for backward compatibility).

### Coordinate Labels

Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ graph LR
:maxdepth: 2

usage
metadata_mapping
examples
api
contributing
Expand Down
Loading
Loading