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
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ repos:
- id: yamllint
exclude: pre-commit-config.yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.14.4"
rev: "v0.14.5"
hooks:
- id: ruff-format
- id: ruff-check
Expand Down
56 changes: 48 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,53 @@
# ome-arrow
<img height="200" src="https://raw.githubusercontent.com/wayscience/ome-arrow/main/docs/src/_static/logo.png?raw=true">

OME-Arrow uses OME specifications with Apache Arrow for fast, queryable, and language agnostic bioimage data.
![PyPI - Version](https://img.shields.io/pypi/v/ome-arrow)
[![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)
[![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)
[![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)

Images are often referenced through databases as filepath links instead of the data itself.
OME-Arrow enables image data to be stored alongside metadata or derived data such as single-cell morphology features.
This means you can store and query data from the same location using any system which is compatible with Apache Arrow.
# Open, interoperable, and queryable microscopy images with OME Arrow

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.

<img height="200" src="https://raw.githubusercontent.com/wayscience/ome-arrow/main/docs/src/_static/references_to_files.png">

__Images are often left behind from the data model, referenced but excluded from databases.__

<img height="200" src="https://raw.githubusercontent.com/wayscience/ome-arrow/main/docs/src/_static/various_ome_arrow_schema.png">

__OME-Arrow brings images back into the story.__

OME Arrow enables image data to be stored alongside metadata or derived data such as single-cell morphology features.
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.
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).

## Installation

Install OME Arrow from PyPI or from source:

```sh
# install from pypi
pip install ome-arrow

# install directly from source
pip install git+https://github.com/wayscience/ome-arrow.git
```

## Quick start

See below for a quick start guide.
Please also reference an example notebook: [Learning to fly with OME-Arrow](docs/src/examples/learning_to_fly_with_ome-arrow.ipynb).
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).

```python
from ome_arrow import OMEArrow

# Ingest a tif image through a convenient OME-Arrow class
# Ingest a tif image through a convenient OME Arrow class
# We can also ingest OME-Zarr or NumPy arrays.
oa_image = OMEArrow(
data="your_image.tif"
)

# Access the OME-Arrow struct itself
# Access the OME Arrow struct itself
# (compatible with Arrow-compliant data storage).
oa_image.data

Expand All @@ -38,3 +65,16 @@ oa_image.view(how="pyvista")
# We can also export OME-TIFF, OME-Zarr or NumPy arrays.
oa_image.export(how="ome-parquet", out="your_image.ome.parquet")
```

## Contributing, Development, and Testing

Please see our [contributing documentation](https://github.com/wayscience/ome-arrow/tree/main/CONTRIBUTING.md) for more details on contributions, development, and testing.

## Related projects

OME Arrow is used or inspired by the following projects, check them out!

- [`napari-ome-arrow`](https://github.com/WayScience/napari-ome-arrow): enables you to view OME Arrow and related images.
- [`nViz`](https://github.com/WayScience/nViz): focuses on ingesting and visualizing various 3D image data.
- [`CytoDataFrame`](https://github.com/cytomining/CytoDataFrame): provides a DataFrame-like experience for viewing feature and microscopy image data within Jupyter notebook interfaces.
- [`coSMicQC`](https://github.com/cytomining/coSMicQC): performs quality control on microscopy feature datasets, visualized using CytoDataFrames.
Binary file added docs/src/_static/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/src/_static/references_to_files.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/src/_static/various_ome_arrow_schema.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 47 additions & 21 deletions docs/src/examples/learning_to_fly_with_ome-arrow.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
"id": "d778aece-5867-49b6-8890-f5a387f22c44",
"metadata": {},
"source": [
"# Learning to fly with OME-Arrow\n"
"# Learning to fly with OME-Arrow\n",
"\n",
"This notebook provides a quick demonstration of what you can do with OME Arrow."
]
},
{
Expand All @@ -15,6 +17,8 @@
"metadata": {},
"outputs": [],
"source": [
"# we import a single class, OMEArrow\n",
"# which handles all data I/O and manipulation\n",
"from ome_arrow import OMEArrow"
]
},
Expand All @@ -30,7 +34,7 @@
"2D image, single-channel - shape (T=1, C=1, Z=1, Y=512, X=512)"
],
"text/plain": [
"<ome_arrow.core.OMEArrow at 0x169de7d90>"
"<ome_arrow.core.OMEArrow at 0x162d227d0>"
]
},
"execution_count": 2,
Expand All @@ -49,9 +53,11 @@
}
],
"source": [
"# read a TIFF file and convert it to OME-Arrow\n",
"oa_image = OMEArrow(\n",
" data=\"../../../tests/data/examplehuman/AS_09125_050116030001_D03f00d0.tif\"\n",
")\n",
"# by default, the image and metadata are shown\n",
"oa_image"
]
},
Expand All @@ -77,6 +83,7 @@
}
],
"source": [
"# we can also get a summary of the OME-Arrow object\n",
"oa_image.info()"
]
},
Expand Down Expand Up @@ -105,6 +112,8 @@
}
],
"source": [
"# we can export the data into a number\n",
"# of different formats, e.g. numpy\n",
"oa_image.export(how=\"numpy\")"
]
},
Expand All @@ -120,7 +129,7 @@
"3D image (z-stack), multi-channel (2 channels) - shape (T=1, C=2, Z=22, Y=128, X=128)"
],
"text/plain": [
"<ome_arrow.core.OMEArrow at 0x31d2e8550>"
"<ome_arrow.core.OMEArrow at 0x1662b2810>"
]
},
"execution_count": 5,
Expand All @@ -139,28 +148,31 @@
}
],
"source": [
"# We can also read in TIFF stacks following OME bfconvert API conventions\n",
"stack = OMEArrow(\n",
" data=\"../../../tests/data/nviz-artificial-4d-dataset/E99_C<111,222>_ZS<000-021>.tif\",\n",
" # this is an optional for which\n",
" # timepoint, channel, and z-slice to show by default\n",
" tcz=(0, 0, 20),\n",
")\n",
"stack"
]
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 6,
"id": "383e1f10-b32f-47cb-9906-15dd9947b09a",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "cf00f3c09cc340f792d8811b76cc739b",
"model_id": "e644f91c4e3843c39f130f05b628277e",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Widget(value='<iframe src=\"http://localhost:65381/index.html?ui=P_0x3620ef510_0&reconnect=auto\" class=\"pyvista…"
"Widget(value='<iframe src=\"http://localhost:55867/index.html?ui=P_0x1663cf990_0&reconnect=auto\" class=\"pyvista…"
]
},
"metadata": {},
Expand All @@ -186,21 +198,22 @@
{
"data": {
"text/plain": [
"<pyvista.plotting.plotter.Plotter at 0x3620ef510>"
"<pyvista.plotting.plotter.Plotter at 0x1663cf990>"
]
},
"execution_count": 10,
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# we can visualize the stack using pyvista for 3D rendering\n",
"stack.view(how=\"pyvista\")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 7,
"id": "d041ba28-bb16-4833-9661-9c9da2ff3a9c",
"metadata": {},
"outputs": [
Expand All @@ -210,10 +223,10 @@
"3D image (z-stack), multi-channel (2 channels) - shape (T=1, C=2, Z=22, Y=128, X=128)"
],
"text/plain": [
"<ome_arrow.core.OMEArrow at 0x31d3a9790>"
"<ome_arrow.core.OMEArrow at 0x10aae1ad0>"
]
},
"execution_count": 6,
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
},
Expand All @@ -229,13 +242,16 @@
}
],
"source": [
"# here we demonstrate that the data can be exported again\n",
"# into numpy format and re-imported\n",
"# into a new OME-Arrow object (from numpy data).\n",
"stack_np = stack.export(how=\"numpy\")\n",
"OMEArrow(data=stack_np, tcz=(0, 0, 20))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 8,
"id": "013baec4-0fed-452c-b200-cfd3b5f04d3e",
"metadata": {},
"outputs": [
Expand All @@ -245,10 +261,10 @@
"3D image (z-stack), multi-channel (2 channels) - shape (T=1, C=2, Z=22, Y=128, X=128)"
],
"text/plain": [
"<ome_arrow.core.OMEArrow at 0x31d3e1710>"
"<ome_arrow.core.OMEArrow at 0x1662019d0>"
]
},
"execution_count": 7,
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
},
Expand All @@ -264,13 +280,16 @@
}
],
"source": [
"# here we demonstrate that the data can be exported again\n",
"# into OME-TIFF format and re-imported\n",
"# into a new OME-Arrow object (from OME-TIFF data).\n",
"stack.export(how=\"ome-tiff\", out=\"example.ome.tiff\")\n",
"OMEArrow(data=\"example.ome.tiff\", tcz=(0, 0, 20))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 9,
"id": "ebaab572-f820-4402-9dd7-2ad5ce657e05",
"metadata": {},
"outputs": [
Expand All @@ -280,10 +299,10 @@
"3D image (z-stack), multi-channel (2 channels) - shape (T=1, C=2, Z=22, Y=128, X=128)"
],
"text/plain": [
"<ome_arrow.core.OMEArrow at 0x31d3521d0>"
"<ome_arrow.core.OMEArrow at 0x1663adad0>"
]
},
"execution_count": 8,
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
},
Expand All @@ -299,13 +318,16 @@
}
],
"source": [
"# here we demonstrate that the data can be exported again\n",
"# into OME-ZARR format and re-imported\n",
"# into a new OME-Arrow object (from OME-ZARR data).\n",
"stack.export(how=\"ome-zarr\", out=\"example.ome.zarr\")\n",
"OMEArrow(data=\"example.ome.zarr\", tcz=(0, 0, 20))"
]
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 10,
"id": "11b5c23c-d4b1-4170-ad0c-64c358b0cfe6",
"metadata": {},
"outputs": [
Expand All @@ -315,10 +337,10 @@
"3D image (z-stack), multi-channel (2 channels) - shape (T=1, C=2, Z=22, Y=128, X=128)"
],
"text/plain": [
"<ome_arrow.core.OMEArrow at 0x31d349d50>"
"<ome_arrow.core.OMEArrow at 0x38064c810>"
]
},
"execution_count": 9,
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
},
Expand All @@ -334,6 +356,9 @@
}
],
"source": [
"# here we demonstrate that the data can be exported again\n",
"# into OME-Parquet format and re-imported\n",
"# into a new OME-Arrow object (from OME-Parquet data).\n",
"stack.export(how=\"ome-parquet\", out=\"example.ome.parquet\")\n",
"OMEArrow(data=\"example.ome.parquet\", tcz=(0, 0, 20))"
]
Expand All @@ -350,7 +375,7 @@
"2D image, single-channel - shape (T=1, C=1, Z=1, Y=30, X=30)"
],
"text/plain": [
"<ome_arrow.core.OMEArrow at 0x31d385f10>"
"<ome_arrow.core.OMEArrow at 0x167243690>"
]
},
"execution_count": 11,
Expand All @@ -369,6 +394,7 @@
}
],
"source": [
"# we can also slice the data to get a smaller region of interest\n",
"stack.slice(\n",
" x_min=40,\n",
" y_min=80,\n",
Expand Down
Loading