ome-arrow 0.0.2__py3-none-any.whl → 0.0.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ome_arrow/_version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.0.2'
32
- __version_tuple__ = version_tuple = (0, 0, 2)
31
+ __version__ = version = '0.0.4'
32
+ __version_tuple__ = version_tuple = (0, 0, 4)
33
33
 
34
34
  __commit_id__ = commit_id = None
ome_arrow/core.py CHANGED
@@ -5,12 +5,11 @@ Core of the ome_arrow package, used for classes and such.
5
5
  from __future__ import annotations
6
6
 
7
7
  import pathlib
8
- from typing import Any, Dict, Iterable, Optional, Tuple
8
+ from typing import TYPE_CHECKING, Any, Dict, Iterable, Optional, Tuple
9
9
 
10
10
  import matplotlib
11
11
  import numpy as np
12
12
  import pyarrow as pa
13
- import pyvista
14
13
 
15
14
  from ome_arrow.export import to_numpy, to_ome_parquet, to_ome_tiff, to_ome_zarr
16
15
  from ome_arrow.ingest import (
@@ -25,6 +24,10 @@ from ome_arrow.transform import slice_ome_arrow
25
24
  from ome_arrow.utils import describe_ome_arrow
26
25
  from ome_arrow.view import view_matplotlib, view_pyvista
27
26
 
27
+ # if not in runtime, import pyvista for type hints
28
+ if TYPE_CHECKING:
29
+ import pyvista
30
+
28
31
 
29
32
  class OMEArrow:
30
33
  """
@@ -47,6 +50,8 @@ class OMEArrow:
47
50
  self,
48
51
  data: str | dict | pa.StructScalar | "np.ndarray",
49
52
  tcz: Tuple[int, int, int] = (0, 0, 0),
53
+ column_name: str = "ome_arrow",
54
+ row_index: int = 0,
50
55
  ) -> None:
51
56
  """
52
57
  Construct an OMEArrow from:
@@ -91,7 +96,9 @@ class OMEArrow:
91
96
  ".parquet",
92
97
  ".pq",
93
98
  }:
94
- self.data = from_ome_parquet(s)
99
+ self.data = from_ome_parquet(
100
+ s, column_name=column_name, row_index=row_index
101
+ )
95
102
 
96
103
  # TIFF
97
104
  elif path.suffix.lower() in {".tif", ".tiff"} or s.lower().endswith(
@@ -293,7 +300,7 @@ class OMEArrow:
293
300
  clim: tuple[float, float] | None = None,
294
301
  show_axes: bool = True,
295
302
  scaling_values: tuple[float, float, float] | None = (1.0, 0.1, 0.1),
296
- ) -> matplotlib.figure.Figure | pyvista.Plotter:
303
+ ) -> matplotlib.figure.Figure | "pyvista.Plotter":
297
304
  """
298
305
  Render an OME-Arrow record using Matplotlib or PyVista.
299
306
 
ome_arrow/ingest.py CHANGED
@@ -4,6 +4,7 @@ Converting to and from OME-Arrow formats.
4
4
 
5
5
  import itertools
6
6
  import re
7
+ import warnings
7
8
  from datetime import datetime, timezone
8
9
  from pathlib import Path
9
10
  from typing import Any, Dict, List, Optional, Sequence, Tuple
@@ -820,42 +821,6 @@ def from_ome_parquet(
820
821
  ) -> pa.StructScalar:
821
822
  """
822
823
  Read an OME-Arrow record from a Parquet file and return a typed StructScalar.
823
-
824
- Expected layout (as produced by `to_ome_parquet`):
825
- - single Parquet file
826
- - a single column (default name "ome_arrow") of `OME_ARROW_STRUCT` type
827
- - one row (row_index=0)
828
-
829
- This function is forgiving:
830
- - If `column_name` is None or not found, it will auto-detect a struct column
831
- that matches the OME-Arrow field names.
832
- - If the table has multiple rows, you can choose which record to read
833
- via `row_index`.
834
-
835
- Parameters
836
- ----------
837
- parquet_path : str | Path
838
- Path to the .parquet file.
839
- column_name : Optional[str], default "ome_arrow"
840
- Name of the column that stores the OME-Arrow struct. If None, auto-detect.
841
- row_index : int, default 0
842
- Which row to read if the table contains multiple rows.
843
- strict_schema : bool, default False
844
- If True, require the column's type to equal `OME_ARROW_STRUCT` exactly.
845
- If False, we only require the column to be a Struct with the same field
846
- names (order can vary).
847
-
848
- Returns
849
- -------
850
- pa.StructScalar
851
- A validated OME-Arrow struct scalar.
852
-
853
- Raises
854
- ------
855
- FileNotFoundError
856
- If the file does not exist.
857
- ValueError
858
- If a suitable column/row cannot be found or schema checks fail.
859
824
  """
860
825
  p = Path(parquet_path)
861
826
  if not p.exists():
@@ -874,7 +839,9 @@ def from_ome_parquet(
874
839
  col_fields = {f.name for f in t}
875
840
  return ome_fields == col_fields
876
841
 
842
+ requested_name = column_name
877
843
  candidate_col = None
844
+ autodetected_name = None
878
845
 
879
846
  if column_name is not None and column_name in table.column_names:
880
847
  arr = table[column_name]
@@ -898,10 +865,12 @@ def from_ome_parquet(
898
865
  if pa.types.is_struct(arr.type):
899
866
  if strict_schema and arr.type == OME_ARROW_STRUCT:
900
867
  candidate_col = arr
868
+ autodetected_name = name
901
869
  column_name = name
902
870
  break
903
871
  if not strict_schema and _struct_matches_ome_fields(arr.type):
904
872
  candidate_col = arr
873
+ autodetected_name = name
905
874
  column_name = name
906
875
  break
907
876
  if candidate_col is None:
@@ -911,21 +880,26 @@ def from_ome_parquet(
911
880
  hint = f"column '{column_name}' not found and auto-detection failed."
912
881
  raise ValueError(f"Could not locate an OME-Arrow struct column: {hint}")
913
882
 
883
+ # Emit warning if auto-detection was used
884
+ if autodetected_name is not None and autodetected_name != requested_name:
885
+ warnings.warn(
886
+ f"Requested column '{requested_name}' was not usable or not found. "
887
+ f"Auto-detected OME-Arrow column '{autodetected_name}'.",
888
+ UserWarning,
889
+ stacklevel=2,
890
+ )
891
+
914
892
  # 2) Extract the row as a Python dict
915
- # (Using to_pylist() for the single element slice is simple & reliable.)
916
893
  record_dict: Dict[str, Any] = candidate_col.slice(row_index, 1).to_pylist()[0]
917
894
 
918
895
  # 3) Reconstruct a typed StructScalar using the canonical schema
919
- # (this validates field names/types and normalizes order)
920
896
  scalar = pa.scalar(record_dict, type=OME_ARROW_STRUCT)
921
897
 
922
898
  # Optional: soft validation via file-level metadata (if present)
923
899
  try:
924
900
  meta = table.schema.metadata or {}
925
- meta.get(b"ome.arrow.type", b"").decode() == str(
926
- OME_ARROW_TAG_TYPE
927
- ) and meta.get(b"ome.arrow.version", b"").decode() == str(OME_ARROW_TAG_VERSION)
928
- # You could log/print a warning if tag_ok is False, but don't fail.
901
+ meta.get(b"ome.arrow.type", b"").decode() == str(OME_ARROW_TAG_TYPE)
902
+ meta.get(b"ome.arrow.version", b"").decode() == str(OME_ARROW_TAG_VERSION)
929
903
  except Exception:
930
904
  pass
931
905
 
ome_arrow/view.py CHANGED
@@ -2,16 +2,27 @@
2
2
  Viewing utilities for OME-Arrow data.
3
3
  """
4
4
 
5
+ from __future__ import annotations
6
+
5
7
  import contextlib
8
+ import warnings
9
+ from typing import TYPE_CHECKING
6
10
 
7
11
  import matplotlib.pyplot as plt
8
12
  import numpy as np
9
13
  import pyarrow as pa
10
- import pyvista as pv
11
14
  from matplotlib.axes import Axes
12
15
  from matplotlib.figure import Figure
13
16
  from matplotlib.image import AxesImage
14
17
 
18
+ try: # optional dependency
19
+ import pyvista as pv
20
+ except ImportError: # pragma: no cover - exercised when viz extra missing
21
+ pv = None # type: ignore[assignment]
22
+
23
+ if TYPE_CHECKING:
24
+ import pyvista
25
+
15
26
 
16
27
  def view_matplotlib(
17
28
  data: dict[str, object] | pa.StructScalar,
@@ -63,6 +74,21 @@ def view_matplotlib(
63
74
  return fig, ax, im
64
75
 
65
76
 
77
+ def _require_pyvista() -> "pyvista":
78
+ """
79
+ Ensure PyVista is available, raising a helpful error otherwise.
80
+ """
81
+ if pv is None:
82
+ msg = (
83
+ "PyVista-based visualization requires the optional 'viz' extras. "
84
+ "Install with `pip install ome-arrow[viz]` to enable 3D viewing."
85
+ )
86
+ warnings.warn(msg, RuntimeWarning)
87
+ raise RuntimeError(msg)
88
+
89
+ return pv
90
+
91
+
66
92
  def view_pyvista(
67
93
  data: dict | pa.StructScalar,
68
94
  c: int = 0,
@@ -77,16 +103,14 @@ def view_pyvista(
77
103
  percentile_clim: tuple[float, float] = (1.0, 99.9), # robust contrast
78
104
  sampling_scale: float = 0.5, # smaller = denser rays (sharper, slower)
79
105
  show: bool = True,
80
- ) -> pv.Plotter:
106
+ ) -> "pyvista.Plotter":
81
107
  """
82
108
  Jupyter-inline interactive volume view using PyVista backends.
83
109
  Tries 'trame' → 'html' → 'static' when backend='auto'.
84
110
 
85
111
  sampling_scale controls ray step via the mapper after add_volume.
86
112
  """
87
- import warnings
88
-
89
- import numpy as np
113
+ pv = _require_pyvista()
90
114
 
91
115
  # ---- unwrap OME-Arrow row
92
116
  row = data.as_py() if isinstance(data, pa.StructScalar) else data
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: ome-arrow
3
+ Version: 0.0.4
4
+ Summary: Using OME specifications with Apache Arrow for fast, queryable, and language agnostic bioimage data.
5
+ Author: Dave Bunten
6
+ Classifier: Programming Language :: Python :: 3 :: Only
7
+ Classifier: Programming Language :: Python :: 3.11
8
+ Classifier: Programming Language :: Python :: 3.12
9
+ Classifier: Programming Language :: Python :: 3.13
10
+ Classifier: Programming Language :: Python :: 3.14
11
+ Requires-Python: >=3.11
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: bioio>=3
15
+ Requires-Dist: bioio-ome-tiff>=1.4
16
+ Requires-Dist: bioio-ome-zarr>=3.0.3
17
+ Requires-Dist: bioio-tifffile>=1.3
18
+ Requires-Dist: fire>=0.7
19
+ Requires-Dist: matplotlib>=3.10.7
20
+ Requires-Dist: numpy>=2.2.6
21
+ Requires-Dist: pandas>=2.2.3
22
+ Requires-Dist: pillow>=12
23
+ Requires-Dist: pyarrow>=22
24
+ Provides-Extra: viz
25
+ Requires-Dist: ipywidgets>=8.1.8; extra == "viz"
26
+ Requires-Dist: jupyterlab-widgets>=3.0.16; extra == "viz"
27
+ Requires-Dist: pyvista>=0.46.4; extra == "viz"
28
+ Requires-Dist: trame>=3.12; extra == "viz"
29
+ Requires-Dist: trame-vtk>=2.10; extra == "viz"
30
+ Requires-Dist: trame-vuetify>=3.1; extra == "viz"
31
+ Dynamic: license-file
32
+
33
+ <img height="200" src="https://raw.githubusercontent.com/wayscience/ome-arrow/main/docs/src/_static/logo.png?raw=true">
34
+
35
+ ![PyPI - Version](https://img.shields.io/pypi/v/ome-arrow)
36
+ [![Build Status](https://github.com/wayscience/ome-arrow/actions/workflows/run-tests.yml/badge.svg?branch=main)](https://github.com/wayscience/ome-arrow/actions/workflows/run-tests.yml?query=branch%3Amain)
37
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
38
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
39
+ [![Software DOI badge](https://zenodo.org/badge/DOI/10.5281/zenodo.17664969.svg)](https://doi.org/10.5281/zenodo.17664969)
40
+
41
+ # Open, interoperable, and queryable microscopy images with OME Arrow
42
+
43
+ OME-Arrow uses [Open Microscopy Environment (OME)](https://github.com/ome) specifications through [Apache Arrow](https://arrow.apache.org/) for fast, queryable, and language agnostic bioimage data.
44
+
45
+ <img height="200" src="https://raw.githubusercontent.com/wayscience/ome-arrow/main/docs/src/_static/references_to_files.png">
46
+
47
+ __Images are often left behind from the data model, referenced but excluded from databases.__
48
+
49
+ <img height="200" src="https://raw.githubusercontent.com/wayscience/ome-arrow/main/docs/src/_static/various_ome_arrow_schema.png">
50
+
51
+ __OME-Arrow brings images back into the story.__
52
+
53
+ OME Arrow enables image data to be stored alongside metadata or derived data such as single-cell morphology features.
54
+ Images in OME Arrow are composed of mutlilayer [structs](https://arrow.apache.org/docs/python/generated/pyarrow.struct.html) so they may be stored as values within tables.
55
+ This means you can store, query, and build relationships on data from the same location using any system which is compatible with Apache Arrow (including Parquet) through common data interfaces (such as SQL and DuckDB).
56
+
57
+ ## Project focus
58
+
59
+ This package is intentionally dedicated to work at a per-image level and not large batch handling (though it may be used for those purposes by users or in other projects).
60
+
61
+ - For visualizing OME Arrow and OME Parquet data in Napari, please see the [`napari-ome-arrow`](https://github.com/WayScience/napari-ome-arrow) Napari plugin.
62
+ - For more comprehensive handling of many images and features in the context of the OME Parquet format please see the [`CytoDataFrame`](https://github.com/cytomining/CytoDataFrame) project (and relevant [example notebook](https://github.com/cytomining/CytoDataFrame/blob/main/docs/src/examples/cytodataframe_at_a_glance.ipynb)).
63
+
64
+ ## Installation
65
+
66
+ Install OME Arrow from PyPI or from source:
67
+
68
+ ```sh
69
+ # install from pypi
70
+ pip install ome-arrow
71
+
72
+ # install directly from source
73
+ pip install git+https://github.com/wayscience/ome-arrow.git
74
+ ```
75
+
76
+ ## Quick start
77
+
78
+ See below for a quick start guide.
79
+ Please also reference an example notebook: [Learning to fly with OME-Arrow](https://github.com/wayscience/ome-arrow/tree/main/docs/src/examples/learning_to_fly_with_ome-arrow.ipynb).
80
+
81
+ ```python
82
+ from ome_arrow import OMEArrow
83
+
84
+ # Ingest a tif image through a convenient OME Arrow class
85
+ # We can also ingest OME-Zarr or NumPy arrays.
86
+ oa_image = OMEArrow(
87
+ data="your_image.tif"
88
+ )
89
+
90
+ # Access the OME Arrow struct itself
91
+ # (compatible with Arrow-compliant data storage).
92
+ oa_image.data
93
+
94
+ # Show information about the image.
95
+ oa_image.info()
96
+
97
+ # Display the image with matplotlib.
98
+ oa_image.view(how="matplotlib")
99
+
100
+ # Display the image with pyvista
101
+ # (great for ZYX 3D images; install extras: `pip install 'ome-arrow[viz]'`).
102
+ oa_image.view(how="pyvista")
103
+
104
+ # Export to OME-Parquet.
105
+ # We can also export OME-TIFF, OME-Zarr or NumPy arrays.
106
+ oa_image.export(how="ome-parquet", out="your_image.ome.parquet")
107
+ ```
108
+
109
+ ## Contributing, Development, and Testing
110
+
111
+ Please see our [contributing documentation](https://github.com/wayscience/ome-arrow/tree/main/CONTRIBUTING.md) for more details on contributions, development, and testing.
112
+
113
+ ## Related projects
114
+
115
+ OME Arrow is used or inspired by the following projects, check them out!
116
+
117
+ - [`napari-ome-arrow`](https://github.com/WayScience/napari-ome-arrow): enables you to view OME Arrow and related images.
118
+ - [`nViz`](https://github.com/WayScience/nViz): focuses on ingesting and visualizing various 3D image data.
119
+ - [`CytoDataFrame`](https://github.com/cytomining/CytoDataFrame): provides a DataFrame-like experience for viewing feature and microscopy image data within Jupyter notebook interfaces and creating OME Parquet files.
120
+ - [`coSMicQC`](https://github.com/cytomining/coSMicQC): performs quality control on microscopy feature datasets, visualized using CytoDataFrames.
@@ -0,0 +1,14 @@
1
+ ome_arrow/__init__.py,sha256=DfQsw8l0mx1Qt3YiiMv2SUljKETP3wS5hrD5eBbjMDM,583
2
+ ome_arrow/_version.py,sha256=QlXZ5JTjE_pgpDaeHk0GTExkc75xUZFmd0hA7kGYCJ0,704
3
+ ome_arrow/core.py,sha256=pTKmzKFXF5d4nSJpXQxlS71UA23P7TLHrX2eA0IxgUg,18594
4
+ ome_arrow/export.py,sha256=CCTnEdHko4Z0i5LEHuNGFLznWSsPyAFcS42H5nHU22Q,14875
5
+ ome_arrow/ingest.py,sha256=7N-M_NYOskHjs59Yhd4j8QXnKC5ykBXM7cT9Ap2chz8,32032
6
+ ome_arrow/meta.py,sha256=qeD0e_ItAQyZDT7ypkBU0rBh9oHIu2ziz9MCfPpPp9g,4199
7
+ ome_arrow/transform.py,sha256=0275_Mn1mlGXSWJ86llch8JoJyvqEOfvG-ub1dUWFNI,5997
8
+ ome_arrow/utils.py,sha256=XHovcqmjqoiBpKvXY47-_yUwf07f8zVE_F9BR_VKaPU,2383
9
+ ome_arrow/view.py,sha256=O4sIF8CZ4if-tV-rr2-yyG8WB5jHN9jq8HKvS-Ielnw,10034
10
+ ome_arrow-0.0.4.dist-info/licenses/LICENSE,sha256=9-2Pyhu3vTt2RJU8DorHQtHeNO_e5RLeFJTyOU4hOi4,1508
11
+ ome_arrow-0.0.4.dist-info/METADATA,sha256=2al9lOlUBjuximxy-1L9TsbVkFC46o0_zR3T1EnFRtU,5908
12
+ ome_arrow-0.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
+ ome_arrow-0.0.4.dist-info/top_level.txt,sha256=aWOtkGXo_pfU-yy82guzGhz8Zh2h2nFl8Kc5qdzMGuE,10
14
+ ome_arrow-0.0.4.dist-info/RECORD,,
@@ -1,34 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: ome-arrow
3
- Version: 0.0.2
4
- Summary: Using OME specifications with Apache Arrow for fast, queryable, and language agnostic bioimage data.
5
- Author: Dave Bunten
6
- Classifier: Programming Language :: Python :: 3 :: Only
7
- Classifier: Programming Language :: Python :: 3.11
8
- Classifier: Programming Language :: Python :: 3.12
9
- Classifier: Programming Language :: Python :: 3.13
10
- Classifier: Programming Language :: Python :: 3.14
11
- Requires-Python: >=3.11
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: bioio>=3
15
- Requires-Dist: bioio-ome-tiff>=1.4
16
- Requires-Dist: bioio-ome-zarr>=3.0.3
17
- Requires-Dist: bioio-tifffile>=1.3
18
- Requires-Dist: fire>=0.7
19
- Requires-Dist: ipywidgets>=8.1.8
20
- Requires-Dist: jupyterlab-widgets>=3.0.16
21
- Requires-Dist: matplotlib>=3.10.7
22
- Requires-Dist: numpy>=2.2.6
23
- Requires-Dist: pandas>=2.2.3
24
- Requires-Dist: pillow>=12
25
- Requires-Dist: pyarrow>=22
26
- Requires-Dist: pyvista>=0.46.4
27
- Requires-Dist: trame>=3.12
28
- Requires-Dist: trame-vtk>=2.10
29
- Requires-Dist: trame-vuetify>=3.1
30
- Dynamic: license-file
31
-
32
- # ome-arrow
33
-
34
- Using OME specifications with Apache Arrow for fast, queryable, and language agnostic bioimage data.
@@ -1,14 +0,0 @@
1
- ome_arrow/__init__.py,sha256=DfQsw8l0mx1Qt3YiiMv2SUljKETP3wS5hrD5eBbjMDM,583
2
- ome_arrow/_version.py,sha256=huLsL1iGeXWQKZ8bjwDdIWC7JOkj3wnzBh-HFMZl1PY,704
3
- ome_arrow/core.py,sha256=NUCV9KUH3yCOlpetRS5NNVG_phodutE1F2ujDBPhHgY,18351
4
- ome_arrow/export.py,sha256=CCTnEdHko4Z0i5LEHuNGFLznWSsPyAFcS42H5nHU22Q,14875
5
- ome_arrow/ingest.py,sha256=zZz94LaLOpmoxnryLeoPsaWV0EzkYkGFizYSVcbd5w8,33016
6
- ome_arrow/meta.py,sha256=qeD0e_ItAQyZDT7ypkBU0rBh9oHIu2ziz9MCfPpPp9g,4199
7
- ome_arrow/transform.py,sha256=0275_Mn1mlGXSWJ86llch8JoJyvqEOfvG-ub1dUWFNI,5997
8
- ome_arrow/utils.py,sha256=XHovcqmjqoiBpKvXY47-_yUwf07f8zVE_F9BR_VKaPU,2383
9
- ome_arrow/view.py,sha256=DT8i56uV8Rw22KkqwjPPPKWJWNtfgR9OkI8Qj1WD8Ds,9355
10
- ome_arrow-0.0.2.dist-info/licenses/LICENSE,sha256=9-2Pyhu3vTt2RJU8DorHQtHeNO_e5RLeFJTyOU4hOi4,1508
11
- ome_arrow-0.0.2.dist-info/METADATA,sha256=XrGmDrHe-QMpEeDzUP4hVEmfh1P4Z8qyGMmGuMPWsfo,1164
12
- ome_arrow-0.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
- ome_arrow-0.0.2.dist-info/top_level.txt,sha256=aWOtkGXo_pfU-yy82guzGhz8Zh2h2nFl8Kc5qdzMGuE,10
14
- ome_arrow-0.0.2.dist-info/RECORD,,