Skip to content

Commit 13d91d6

Browse files
authored
Merge pull request #30 from funkelab/zarr3
bumps version up to 0.7 since it adds quite a few changes, some of which are not backwards compatible. Breaking change: - now depends on python 3.11 or above. This is necessary because we rely on iohub for zarr3 compatibility which supports only python 3.11 and above. Other changes: - bulk write api. Added `bulk_write_nodes`, `bulk_write_edges` and `bulk_write_graph`. These use more efficient forms of insert queries into the relevant databases to better handle large amounts of data. Some features of the existing write api may be unavailable (`fail_if_exists` for example) - bulk write context manager. Graph providers now have a bulk write context manager whose primary purpose is to remove indexes on enter and rebuild on exit. Note that you do not want to call this on workers. There is a flag to call on workers which can be helpful and will do things like turn of synchronous commits. minor improvements and bug fixes: - removed duplicate conditions on queries with attribute filters - Better respect half open properties of ROI requests. Sometimes nodes would get through before if exactly on the upper bound. - Better ROI queries for edges. Instead of fetching all nodes in a ROI and then serializing the list of nodes into a string to put in the SQL query, we now send a single request with a JOIN statement to both read nodes in roi and match on endpoints to get edges. This results in faster reads and won't run into the memory issues occasionally encountered before. Note if using a node attribute filter it will still fetch nodes first matching that criteria, then serialize to string and query edges with u contained in list of nodes. Tests: - greatly expanded tests for new features and bug fixes
2 parents b9bb116 + d5b3e7d commit 13d91d6

28 files changed

Lines changed: 1499 additions & 743 deletions

.github/workflows/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
strategy:
1212
fail-fast: false
1313
matrix:
14-
python-version: ["3.10", "3.11", "3.12"]
14+
python-version: ["3.11", "3.12", "3.13"]
1515
resolution: ["highest", "lowest-direct"]
1616

1717
services:
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
name: mypy
1+
name: ty
22

33
on: [push, pull_request]
44

55
jobs:
66
static-analysis:
7-
name: Python mypy
7+
name: Python ty
88
runs-on: ubuntu-latest
99
steps:
1010
- name: Setup checkout
1111
uses: actions/checkout@master
1212
- name: Install uv
1313
uses: astral-sh/setup-uv@main
14-
- name: mypy
15-
run: uv run --extra dev mypy funlib/persistence tests
14+
- name: ty
15+
run: uv run --extra dev ty check src tests

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,5 @@ dmypy.json
130130
.vscode/
131131

132132
*.sw[pmno]
133+
daisy_logs
134+
uv.lock

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[![tests](https://github.com/funkelab/funlib.persistence/actions/workflows/tests.yaml/badge.svg)](https://github.com/funkelab/funlib.persistence/actions/workflows/tests.yaml)
22
[![ruff](https://github.com/funkelab/funlib.persistence/actions/workflows/ruff.yaml/badge.svg)](https://github.com/funkelab/funlib.persistence/actions/workflows/ruff.yaml)
3-
[![mypy](https://github.com/funkelab/funlib.persistence/actions/workflows/mypy.yaml/badge.svg)](https://github.com/funkelab/funlib.persistence/actions/workflows/mypy.yaml)
3+
[![ty](https://github.com/funkelab/funlib.persistence/actions/workflows/ty.yaml/badge.svg)](https://github.com/funkelab/funlib.persistence/actions/workflows/ty.yaml)
44
[![pypi](https://github.com/funkelab/funlib.persistence/actions/workflows/publish.yaml/badge.svg)](https://pypi.org/project/funlib.persistence/)
55

66
# funlib.persistence

funlib/persistence/arrays/lazy_ops.py

Lines changed: 0 additions & 5 deletions
This file was deleted.

funlib/persistence/graphs/pgsql_graph_database.py

Lines changed: 0 additions & 206 deletions
This file was deleted.

pyproject.toml

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,21 @@ authors = [
1313
]
1414
dynamic = ['version']
1515

16-
requires-python = ">=3.10"
16+
requires-python = ">=3.11"
1717
classifiers = ["Programming Language :: Python :: 3"]
1818
keywords = []
1919

2020
dependencies = [
21-
"zarr>=2,<3",
22-
# ImportError: cannot import name 'cbuffer_sizes' from 'numcodecs.blosc'
23-
# We can pin zarr to >2.18.7 but then we have to drop python 3.10
24-
# pin numcodecs to avoid breaking change
25-
"numcodecs>0.13,<0.16.0",
26-
"iohub>=0.2.0b0",
21+
"zarr>=3,<4",
22+
"iohub>=0.3.0a5",
2723
"funlib.geometry>=0.3.0",
2824
"networkx>=3.0.0",
2925
"pymongo>=4.0.0",
3026
"numpy>=2.0.0",
3127
"pydantic>=2.0.0",
3228
"dask>=2024.0.0",
3329
"toml>=0.10.0",
34-
"psycopg2-binary>=2.9.5",
30+
"psycopg2-binary>=2.9.11",
3531
]
3632

3733
[tool.setuptools.dynamic]
@@ -40,10 +36,10 @@ version = { attr = "funlib.persistence.__version__" }
4036
[project.optional-dependencies]
4137
dev = [
4238
"coverage>=7.7.1",
43-
"mypy>=1.15.0",
4439
"pytest>=8.3.5",
4540
"pytest-mock>=3.14.0",
4641
"ruff>=0.11.2",
42+
"ty>=0.0.16",
4743
"types-networkx",
4844
"types-psycopg2",
4945
"types-toml",
@@ -56,10 +52,8 @@ lint.select = ["F", "W", "I001"]
5652
[tool.setuptools.package-data]
5753
"funlib.persistence" = ["py.typed"]
5854

59-
[tool.mypy]
60-
explicit_package_bases = true
61-
6255
# # module specific overrides
6356
[[tool.mypy.overrides]]
6457
module = ["zarr.*", "iohub.*"]
6558
ignore_missing_imports = true
59+
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
from .arrays import Array, open_ds, prepare_ds, open_ome_ds, prepare_ome_ds # noqa
22

3-
__version__ = "0.6.1"
3+
__version__ = "0.7.0"
44
__version_info__ = tuple(int(i) for i in __version__.split("."))
Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
import dask.array as da
77
import numpy as np
88
from dask.array.optimization import fuse_slice
9-
from zarr import Array as ZarrArray
10-
119
from funlib.geometry import Coordinate, Roi
10+
from zarr import Array as ZarrArray
1211

1312
from .freezable import Freezable
1413
from .lazy_ops import LazyOp
@@ -135,7 +134,7 @@ def attrs(self) -> dict:
135134

136135
@property
137136
def chunk_shape(self) -> Coordinate:
138-
return Coordinate(self.data.chunksize)
137+
return Coordinate(self.data.chunksize) # ty: ignore[unresolved-attribute]
139138

140139
def uncollapsed_dims(self, physical: bool = False) -> list[bool]:
141140
"""
@@ -344,18 +343,21 @@ def __getitem__(self, key) -> np.ndarray:
344343
else:
345344
return self.data[key].compute()
346345

347-
def __setitem__(self, key, value: np.ndarray):
348-
"""Set the data of this array within the given ROI.
346+
def __setitem__(self, key: Roi | slice | tuple, value: np.ndarray | float | int):
347+
"""Set the data of this array.
349348
350349
Args:
351350
352-
key (`class:Roi`):
351+
key (`class:Roi` or any numpy compatible key):
353352
354-
The ROI to write to.
353+
The region to write to. Can be a `Roi` for world-unit indexing,
354+
or any numpy-compatible key (e.g. ``np.s_[:]``, a slice, a tuple
355+
of slices).
355356
356-
value (``ndarray``):
357+
value (``ndarray`` or scalar):
357358
358-
The value to write.
359+
The value to write. Can be a numpy array or a scalar that will
360+
be broadcast.
359361
"""
360362

361363
if self.is_writeable:
@@ -474,7 +476,7 @@ def _is_slice(self, lazy_op: LazyOp, writeable: bool = False) -> bool:
474476
elif isinstance(lazy_op, list) and all([isinstance(a, int) for a in lazy_op]):
475477
return True
476478
elif isinstance(lazy_op, tuple) and all(
477-
[self._is_slice(a, writeable) for a in lazy_op]
479+
[self._is_slice(a, writeable) for a in lazy_op] # type: ignore[arg-type] # ty can't narrow parameterized tuple iteration
478480
):
479481
return True
480482
elif (
@@ -508,7 +510,7 @@ def validate(self, strict: bool = False):
508510
)
509511

510512
def to_pixel_space(
511-
self, world_loc: Roi | Coordinate | Sequence[int | float]
513+
self, world_loc: Roi | Coordinate | Sequence[int | float] | np.ndarray
512514
) -> Roi | Coordinate | np.ndarray:
513515
"""Convert a point or roi in world space into the pixel space of this array.
514516
Works on sequences of floats by returning a numpy array that is not guaranteed
@@ -539,7 +541,7 @@ def to_pixel_space(
539541
)
540542

541543
def to_world_space(
542-
self, pixel_loc: Roi | Coordinate | Sequence[int | float]
544+
self, pixel_loc: Roi | Coordinate | Sequence[int | float] | np.ndarray
543545
) -> Roi | Coordinate:
544546
"""Convert a point or roi from pixel space in this array to the world
545547
coordinate system defined by this array's roi and voxel size.

0 commit comments

Comments
 (0)