diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..94db649 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @maltekuehl diff --git a/pyproject.toml b/pyproject.toml index 556bafd..113c335 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ packages = ["spatiomic"] [project] name = "spatiomic" -version = "0.8.0" +version = "0.9.0" description = "A python toolbox for spatial omics analysis." requires-python = ">=3.11" license = { file = "LICENSE" } @@ -206,18 +206,18 @@ dev = [ [project.optional-dependencies] cellpose = ["cellpose>=4.0.1,<5"] -spatialdata = ["spatialdata==0.5.0"] +spatialdata = ["spatialdata==0.6.1"] cuda-12 = [ - "cuml-cu12>=24.6.0", - "cugraph-cu12>=24.6.0", - "nx-cugraph-cu12>=24.6.0", - "cucim-cu12>=24.6.0", + "cuml-cu12>=24.10.0", + "cugraph-cu12>=24.10.0", + "nx-cugraph-cu12>=24.10.0", + "cucim-cu12>=24.10.0", ] cuda-11 = [ - "cuml-cu11>=24.6.0", - "cugraph-cu11>=24.6.0", - "nx-cugraph-cu11>=24.6.0", - "cucim-cu11>=24.6.0", + "cuml-cu11>=24.10.0", + "cugraph-cu11>=24.10.0", + "nx-cugraph-cu11>=24.10.0", + "cucim-cu11>=24.10.0", ] [tool.uv] diff --git a/spatiomic/process/_register.py b/spatiomic/process/_register.py index c334d63..45f3e01 100755 --- a/spatiomic/process/_register.py +++ b/spatiomic/process/_register.py @@ -11,27 +11,122 @@ class Register: """Expose registration methods.""" + @staticmethod + def _preprocess_images( + pixels: NDArray, + reference_pixels: NDArray, + blur: bool = False, + match_histogram: bool = False, + threshold: bool = False, + threshold_percentile: Union[int, float] = 70, + use_gpu: bool = True, + ) -> Tuple[NDArray, NDArray]: + """Preprocess images with optional blur, histogram matching, and thresholding. + + Args: + pixels (NDArray): The pixels to preprocess. + reference_pixels (NDArray): The reference pixels to preprocess. + blur (bool, optional): Whether to apply Gaussian blur. Defaults to False. + match_histogram (bool, optional): Whether to match histograms. Defaults to False. + threshold (bool, optional): Whether to apply thresholding. Defaults to False. + threshold_percentile (Union[int, float], optional): Percentile for thresholding. Defaults to 70. + use_gpu (bool, optional): Whether to use GPU acceleration. Defaults to True. + + Returns: + Tuple[NDArray, NDArray]: The preprocessed pixels and reference pixels. + """ + if use_gpu: + try: + import cupy as cp # type: ignore + + pixels_gpu = cp.array(pixels) + reference_pixels_gpu = cp.array(reference_pixels) + + if blur: + from cucim.skimage.filters import gaussian # type: ignore + + pixels_gpu = gaussian(pixels_gpu) + reference_pixels_gpu = gaussian(reference_pixels_gpu) + + if match_histogram: + from cucim.skimage.exposure import match_histograms # type: ignore + + pixels_gpu = match_histograms(pixels_gpu, reference_pixels_gpu) + + if threshold: + threshold_limit = cp.percentile(reference_pixels_gpu, threshold_percentile) + reference_pixels_gpu = cp.where(reference_pixels_gpu < threshold_limit, 0, reference_pixels_gpu) + pixels_gpu = cp.where(pixels_gpu < threshold_limit, 0, pixels_gpu) + + return pixels_gpu.get(), reference_pixels_gpu.get() # type: ignore + except Exception: + use_gpu = False + + if blur: + from skimage.filters import gaussian + + pixels = gaussian(pixels) + reference_pixels = gaussian(reference_pixels) + + if match_histogram: + from skimage.exposure import match_histograms + + pixels = match_histograms(pixels, reference_pixels) + + if threshold: + threshold_limit = np.percentile(reference_pixels, threshold_percentile) + reference_pixels = np.where(reference_pixels < threshold_limit, 0, reference_pixels) + pixels = np.where(pixels < threshold_limit, 0, pixels) + + return pixels, reference_pixels + @staticmethod def get_ssim( pixels: NDArray, reference_pixels: NDArray, + use_gpu: bool = True, ) -> float: """Calculate the structural similarity index measure. Args: pixels (NDArray): A 2D array of pixels. reference_pixels (NDArray): The 2D reference array for calculation of the structural similarity. + use_gpu (bool, optional): Whether to use the cucim GPU implementation. Defaults to True. Returns: float: The structural similarity index measure. """ + if use_gpu: + try: + import cupy as cp # type: ignore + from cucim.skimage.metrics import ( # type: ignore + structural_similarity, + ) + + pixels = cp.array(pixels) + reference_pixels = cp.array(reference_pixels) + data_range = float(cp.max(pixels) - cp.min(pixels)) + + ssim = structural_similarity( + pixels, + reference_pixels, + full=False, + data_range=data_range, + ) + + return float(ssim.get()) # type: ignore + except Exception: + use_gpu = False + from skimage.metrics import structural_similarity + data_range = float(np.max(pixels) - np.min(pixels)) + ssim = structural_similarity( pixels, reference_pixels, full=False, - data_range=np.max(pixels) - np.min(pixels), + data_range=data_range, ) return float(ssim) @@ -65,30 +160,22 @@ def get_shift( Defaults to "phase_correlation". upsample_factor (int, optional): The upsample factor to use for the phase correlation method. Defaults to 1. - use_gpu (bool, optional): Whether to use the cucim phase_correlation gpu implementation. - Defaults to True. + use_gpu (bool, optional): Whether to use cucim GPU implementations. Defaults to True. Returns: Tuple[float, float]: The offset on the y- and the x-axis. """ - if blur: - from skimage.filters import gaussian - - pixels = gaussian(pixels) - reference_pixels = gaussian(reference_pixels) - - if match_histogram: - from skimage.exposure import match_histograms - - pixels = match_histograms(pixels, reference_pixels) - - if threshold: - threshold_limit = np.percentile(reference_pixels, threshold_percentile) - reference_pixels[reference_pixels < threshold_limit] = 0 - pixels[pixels < threshold_limit] = 0 + pixels, reference_pixels = cls._preprocess_images( + pixels, + reference_pixels, + blur=blur, + match_histogram=match_histogram, + threshold=threshold, + threshold_percentile=threshold_percentile, + use_gpu=use_gpu, + ) if method == "chi2_shift": - # requires image_registration and typing_extensions>=3.10.0.1 and fftw for best performance from image_registration.chi2_shifts import chi2_shift # type: ignore shift = chi2_shift( @@ -105,17 +192,18 @@ def get_shift( (offset_y, offset_x) = cls.get_phase_shift( pixels=pixels, reference_pixels=reference_pixels, - blur=blur, - match_histogram=match_histogram, - threshold=threshold, + blur=False, + match_histogram=False, + threshold=False, use_gpu=use_gpu, upsample_factor=upsample_factor, ) return (offset_y, offset_x) - @staticmethod + @classmethod def get_phase_shift( + cls, pixels: NDArray, reference_pixels: NDArray, blur: bool = False, @@ -137,27 +225,20 @@ def get_phase_shift( percentile of the reference. Defaults to False. upsample_factor (int, optional): The upsample factor to use for the phase correlation method. Defaults to 1. - use_gpu (bool, optional): Whether to use the cucim phase_correlation gpu implementation instead of chi2 - shift. Defaults to True. + use_gpu (bool, optional): Whether to use cucim GPU implementations. Defaults to True. Returns: Tuple[float, float]: The offset on the y- and the x-axis. """ - if blur: - from skimage.filters import gaussian - - pixels = gaussian(pixels) - reference_pixels = gaussian(reference_pixels) - - if match_histogram: - from skimage.exposure import match_histograms - - pixels = match_histograms(pixels, reference_pixels) - - if threshold: - threshold_limit = np.percentile(reference_pixels, 70) # type: ignore - reference_pixels[reference_pixels < threshold_limit] = 0 - pixels[pixels < threshold_limit] = 0 + pixels, reference_pixels = cls._preprocess_images( + pixels, + reference_pixels, + blur=blur, + match_histogram=match_histogram, + threshold=threshold, + threshold_percentile=70, + use_gpu=use_gpu, + ) if use_gpu: try: diff --git a/uv.lock b/uv.lock index 2120d72..bb3f354 100644 --- a/uv.lock +++ b/uv.lock @@ -288,12 +288,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e0/b1/0542e0cab6f49f151a2d7a42400f84f706fc0b64e85dc1f56708b2e9fd37/array_api_compat-1.12.0-py3-none-any.whl", hash = "sha256:a0b4795b6944a9507fde54679f9350e2ad2b1e2acf4a2408a098cdc27f890a8b", size = 58156, upload-time = "2025-05-16T08:49:58.129Z" }, ] -[[package]] -name = "asciitree" -version = "0.3.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2d/6a/885bc91484e1aa8f618f6f0228d76d0e67000b0fdd6090673b777e311913/asciitree-0.3.3.tar.gz", hash = "sha256:4aa4b9b649f85e3fcb343363d97564aa1fb62e249677f2e18a96765145cc0f6e", size = 3951, upload-time = "2016-09-05T19:10:42.681Z" } - [[package]] name = "astroid" version = "3.3.11" @@ -1455,6 +1449,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, ] +[[package]] +name = "donfig" +version = "0.8.1.post1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/25/71/80cc718ff6d7abfbabacb1f57aaa42e9c1552bfdd01e64ddd704e4a03638/donfig-0.8.1.post1.tar.gz", hash = "sha256:3bef3413a4c1c601b585e8d297256d0c1470ea012afa6e8461dc28bfb7c23f52", size = 19506, upload-time = "2024-05-23T14:14:31.513Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/d5/c5db1ea3394c6e1732fb3286b3bd878b59507a8f77d32a2cebda7d7b7cd4/donfig-0.8.1.post1-py3-none-any.whl", hash = "sha256:2a3175ce74a06109ff9307d90a230f81215cbac9a751f4d1c6194644b8204f9d", size = 21592, upload-time = "2024-05-23T14:13:55.283Z" }, +] + [[package]] name = "esda" version = "2.7.1" @@ -1491,15 +1497,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, ] -[[package]] -name = "fasteners" -version = "0.20" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2d/18/7881a99ba5244bfc82f06017316ffe93217dbbbcfa52b887caa1d4f2a6d3/fasteners-0.20.tar.gz", hash = "sha256:55dce8792a41b56f727ba6e123fcaee77fd87e638a6863cec00007bfea84c8d8", size = 25087, upload-time = "2025-08-11T10:19:37.785Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/51/ac/e5d886f892666d2d1e5cb8c1a41146e1d79ae8896477b1153a21711d3b44/fasteners-0.20-py3-none-any.whl", hash = "sha256:9422c40d1e350e4259f509fb2e608d6bc43c0136f79a00db1b49046029d0b3b7", size = 18702, upload-time = "2025-08-11T10:19:35.716Z" }, -] - [[package]] name = "fastjsonschema" version = "2.21.2" @@ -1839,6 +1836,33 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3b/d2/e6b32499fd212ac7f6d2a5db8343460c790a394d9742d96e88f4cca90173/giddy-2.3.6-py3-none-any.whl", hash = "sha256:fbc5fde6798d5e1a4a527a2d80d0856cb24a2be71243cc586c15328868b55d8b", size = 61336, upload-time = "2024-12-12T00:29:05.607Z" }, ] +[[package]] +name = "google-crc32c" +version = "1.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/ae/87802e6d9f9d69adfaedfcfd599266bf386a54d0be058b532d04c794f76d/google_crc32c-1.7.1.tar.gz", hash = "sha256:2bff2305f98846f3e825dbeec9ee406f89da7962accdb29356e4eadc251bd472", size = 14495, upload-time = "2025-03-26T14:29:13.32Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/94/220139ea87822b6fdfdab4fb9ba81b3fff7ea2c82e2af34adc726085bffc/google_crc32c-1.7.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6fbab4b935989e2c3610371963ba1b86afb09537fd0c633049be82afe153ac06", size = 30468, upload-time = "2025-03-26T14:32:52.215Z" }, + { url = "https://files.pythonhosted.org/packages/94/97/789b23bdeeb9d15dc2904660463ad539d0318286d7633fe2760c10ed0c1c/google_crc32c-1.7.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:ed66cbe1ed9cbaaad9392b5259b3eba4a9e565420d734e6238813c428c3336c9", size = 30313, upload-time = "2025-03-26T14:57:38.758Z" }, + { url = "https://files.pythonhosted.org/packages/81/b8/976a2b843610c211e7ccb3e248996a61e87dbb2c09b1499847e295080aec/google_crc32c-1.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee6547b657621b6cbed3562ea7826c3e11cab01cd33b74e1f677690652883e77", size = 33048, upload-time = "2025-03-26T14:41:30.679Z" }, + { url = "https://files.pythonhosted.org/packages/c9/16/a3842c2cf591093b111d4a5e2bfb478ac6692d02f1b386d2a33283a19dc9/google_crc32c-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d68e17bad8f7dd9a49181a1f5a8f4b251c6dbc8cc96fb79f1d321dfd57d66f53", size = 32669, upload-time = "2025-03-26T14:41:31.432Z" }, + { url = "https://files.pythonhosted.org/packages/04/17/ed9aba495916fcf5fe4ecb2267ceb851fc5f273c4e4625ae453350cfd564/google_crc32c-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:6335de12921f06e1f774d0dd1fbea6bf610abe0887a1638f64d694013138be5d", size = 33476, upload-time = "2025-03-26T14:29:10.211Z" }, + { url = "https://files.pythonhosted.org/packages/dd/b7/787e2453cf8639c94b3d06c9d61f512234a82e1d12d13d18584bd3049904/google_crc32c-1.7.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2d73a68a653c57281401871dd4aeebbb6af3191dcac751a76ce430df4d403194", size = 30470, upload-time = "2025-03-26T14:34:31.655Z" }, + { url = "https://files.pythonhosted.org/packages/ed/b4/6042c2b0cbac3ec3a69bb4c49b28d2f517b7a0f4a0232603c42c58e22b44/google_crc32c-1.7.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:22beacf83baaf59f9d3ab2bbb4db0fb018da8e5aebdce07ef9f09fce8220285e", size = 30315, upload-time = "2025-03-26T15:01:54.634Z" }, + { url = "https://files.pythonhosted.org/packages/29/ad/01e7a61a5d059bc57b702d9ff6a18b2585ad97f720bd0a0dbe215df1ab0e/google_crc32c-1.7.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19eafa0e4af11b0a4eb3974483d55d2d77ad1911e6cf6f832e1574f6781fd337", size = 33180, upload-time = "2025-03-26T14:41:32.168Z" }, + { url = "https://files.pythonhosted.org/packages/3b/a5/7279055cf004561894ed3a7bfdf5bf90a53f28fadd01af7cd166e88ddf16/google_crc32c-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d86616faaea68101195c6bdc40c494e4d76f41e07a37ffdef270879c15fb65", size = 32794, upload-time = "2025-03-26T14:41:33.264Z" }, + { url = "https://files.pythonhosted.org/packages/0f/d6/77060dbd140c624e42ae3ece3df53b9d811000729a5c821b9fd671ceaac6/google_crc32c-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:b7491bdc0c7564fcf48c0179d2048ab2f7c7ba36b84ccd3a3e1c3f7a72d3bba6", size = 33477, upload-time = "2025-03-26T14:29:10.94Z" }, + { url = "https://files.pythonhosted.org/packages/8b/72/b8d785e9184ba6297a8620c8a37cf6e39b81a8ca01bb0796d7cbb28b3386/google_crc32c-1.7.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:df8b38bdaf1629d62d51be8bdd04888f37c451564c2042d36e5812da9eff3c35", size = 30467, upload-time = "2025-03-26T14:36:06.909Z" }, + { url = "https://files.pythonhosted.org/packages/34/25/5f18076968212067c4e8ea95bf3b69669f9fc698476e5f5eb97d5b37999f/google_crc32c-1.7.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:e42e20a83a29aa2709a0cf271c7f8aefaa23b7ab52e53b322585297bb94d4638", size = 30309, upload-time = "2025-03-26T15:06:15.318Z" }, + { url = "https://files.pythonhosted.org/packages/92/83/9228fe65bf70e93e419f38bdf6c5ca5083fc6d32886ee79b450ceefd1dbd/google_crc32c-1.7.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:905a385140bf492ac300026717af339790921f411c0dfd9aa5a9e69a08ed32eb", size = 33133, upload-time = "2025-03-26T14:41:34.388Z" }, + { url = "https://files.pythonhosted.org/packages/c3/ca/1ea2fd13ff9f8955b85e7956872fdb7050c4ace8a2306a6d177edb9cf7fe/google_crc32c-1.7.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b211ddaf20f7ebeec5c333448582c224a7c90a9d98826fbab82c0ddc11348e6", size = 32773, upload-time = "2025-03-26T14:41:35.19Z" }, + { url = "https://files.pythonhosted.org/packages/89/32/a22a281806e3ef21b72db16f948cad22ec68e4bdd384139291e00ff82fe2/google_crc32c-1.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:0f99eaa09a9a7e642a61e06742856eec8b19fc0037832e03f941fe7cf0c8e4db", size = 33475, upload-time = "2025-03-26T14:29:11.771Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c5/002975aff514e57fc084ba155697a049b3f9b52225ec3bc0f542871dd524/google_crc32c-1.7.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32d1da0d74ec5634a05f53ef7df18fc646666a25efaaca9fc7dcfd4caf1d98c3", size = 33243, upload-time = "2025-03-26T14:41:35.975Z" }, + { url = "https://files.pythonhosted.org/packages/61/cb/c585282a03a0cea70fcaa1bf55d5d702d0f2351094d663ec3be1c6c67c52/google_crc32c-1.7.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e10554d4abc5238823112c2ad7e4560f96c7bf3820b202660373d769d9e6e4c9", size = 32870, upload-time = "2025-03-26T14:41:37.08Z" }, + { url = "https://files.pythonhosted.org/packages/16/1b/1693372bf423ada422f80fd88260dbfd140754adb15cbc4d7e9a68b1cb8e/google_crc32c-1.7.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85fef7fae11494e747c9fd1359a527e5970fc9603c90764843caabd3a16a0a48", size = 28241, upload-time = "2025-03-26T14:41:45.898Z" }, + { url = "https://files.pythonhosted.org/packages/fd/3c/2a19a60a473de48717b4efb19398c3f914795b64a96cf3fbe82588044f78/google_crc32c-1.7.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6efb97eb4369d52593ad6f75e7e10d053cf00c48983f7a973105bc70b0ac4d82", size = 28048, upload-time = "2025-03-26T14:41:46.696Z" }, +] + [[package]] name = "h5py" version = "3.14.0" @@ -3604,7 +3628,7 @@ wheels = [ [[package]] name = "ome-zarr" -version = "0.11.1" +version = "0.12.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -3616,9 +3640,9 @@ dependencies = [ { name = "toolz" }, { name = "zarr" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/43/25/0e7b247e3e864b93058e5af536407e943edca9f2002c93a9ac04064ff684/ome_zarr-0.11.1.tar.gz", hash = "sha256:f178e336412eaefdb74172b280095cd9bd497bfeb235c1b1c2b0965c21aa1af0", size = 65091, upload-time = "2025-04-23T08:44:40.089Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a4/44/647843d872aa136609e805c06e9f9b2cdcb6e2a58ec485322311dec7b64d/ome_zarr-0.12.2.tar.gz", hash = "sha256:834e801e9aa4b870bed3dde2dc2a3ad7f388f1a13ffa6b3d7aade90691b9de64", size = 69891, upload-time = "2025-08-22T08:57:13.64Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/24/c8/35ac60b20eccccf84638a872c3b4ebefad46b20f87540ca17a37908b1db6/ome_zarr-0.11.1-py3-none-any.whl", hash = "sha256:e8ffc93de78558be990ed3b1b2b186b97ca0c7eb2cb460a7cffb861f4f13a8f1", size = 40000, upload-time = "2025-04-23T08:44:39.077Z" }, + { url = "https://files.pythonhosted.org/packages/4f/21/59baa90924b815b70f88045f0b206b7eab0b68b461c0192692486b516ab7/ome_zarr-0.12.2-py3-none-any.whl", hash = "sha256:655fe1b11ca01148603f9931a5b0af31207dfc03a3a35f9b0ab8639790282bbd", size = 41410, upload-time = "2025-08-22T08:57:12.44Z" }, ] [[package]] @@ -3781,6 +3805,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl", hash = "sha256:978e4ac767ec4ba5b86c6eaa52e5a2a3bc748a2ca839e8cc798f1cc6ce6efb0f", size = 18905, upload-time = "2024-05-06T19:51:39.271Z" }, ] +[[package]] +name = "pathlib-abc" +version = "0.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/cb/448649d7f25d228bf0be3a04590ab7afa77f15e056f8fa976ed05ec9a78f/pathlib_abc-0.5.2.tar.gz", hash = "sha256:fcd56f147234645e2c59c7ae22808b34c364bb231f685ddd9f96885aed78a94c", size = 33342, upload-time = "2025-10-10T18:37:20.524Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/29/c028a0731e202035f0e2e0bfbf1a3e46ad6c628cbb17f6f1cc9eea5d9ff1/pathlib_abc-0.5.2-py3-none-any.whl", hash = "sha256:4c9d94cf1b23af417ce7c0417b43333b06a106c01000b286c99de230d95eefbb", size = 19070, upload-time = "2025-10-10T18:37:19.437Z" }, +] + [[package]] name = "pathspec" version = "0.12.1" @@ -5490,7 +5523,7 @@ wheels = [ [[package]] name = "spatialdata" -version = "0.5.0" +version = "0.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anndata" }, @@ -5498,7 +5531,7 @@ dependencies = [ { name = "dask" }, { name = "dask-image" }, { name = "datashader" }, - { name = "fsspec" }, + { name = "fsspec", extra = ["http", "s3"] }, { name = "geopandas" }, { name = "multiscale-spatial-image" }, { name = "networkx" }, @@ -5515,14 +5548,15 @@ dependencies = [ { name = "shapely" }, { name = "spatial-image" }, { name = "typing-extensions" }, + { name = "universal-pathlib" }, { name = "xarray" }, { name = "xarray-schema" }, { name = "xarray-spatial" }, { name = "zarr" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/31/29/9e7c46cf134854e27996fd4af7d27e184e57f5083b019e9757c4add6a600/spatialdata-0.5.0.tar.gz", hash = "sha256:3c316cdebe7306e887f9383c360993a1db0a7bd1b00b5673d831d23769acf63b", size = 326264, upload-time = "2025-08-15T21:38:50.213Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/78/97a108c20c539a110fd336608d300be568593e047a717ea66ed2e16bdf73/spatialdata-0.6.1.tar.gz", hash = "sha256:d0295feb90b16a6802f13e85780243fe7aecb838b44ba433c304805eac01d555", size = 332031, upload-time = "2025-11-15T15:06:56.74Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/45/f16a66337b05f6c4829d0e9bdc0c6f876e5a193a1cdc1c88f7dee5a3762a/spatialdata-0.5.0-py3-none-any.whl", hash = "sha256:0d513c7da63e4b05a197af70605c51bf074c3fceb81fcdda282637efef425ea6", size = 185333, upload-time = "2025-08-15T21:38:49.045Z" }, + { url = "https://files.pythonhosted.org/packages/17/a1/e538ae38d9424f62199266b4e4ccd780e149162fa828a9e1f7b8e745262e/spatialdata-0.6.1-py3-none-any.whl", hash = "sha256:64a06b481859d22bd72e910c2cfd10af4b6c56be8e78404f096712558cd66ee8", size = 187279, upload-time = "2025-11-15T15:06:54.969Z" }, ] [[package]] @@ -5615,12 +5649,12 @@ requires-dist = [ { name = "astroid", specifier = "==3.3.11" }, { name = "cellpose", marker = "extra == 'cellpose'", specifier = ">=4.0.1,<5" }, { name = "colorcet" }, - { name = "cucim-cu11", marker = "extra == 'cuda-11'", specifier = ">=24.6.0" }, - { name = "cucim-cu12", marker = "extra == 'cuda-12'", specifier = ">=24.6.0" }, - { name = "cugraph-cu11", marker = "extra == 'cuda-11'", specifier = ">=24.6.0" }, - { name = "cugraph-cu12", marker = "extra == 'cuda-12'", specifier = ">=24.6.0" }, - { name = "cuml-cu11", marker = "extra == 'cuda-11'", specifier = ">=24.6.0" }, - { name = "cuml-cu12", marker = "extra == 'cuda-12'", specifier = ">=24.6.0" }, + { name = "cucim-cu11", marker = "extra == 'cuda-11'", specifier = ">=24.10.0" }, + { name = "cucim-cu12", marker = "extra == 'cuda-12'", specifier = ">=24.10.0" }, + { name = "cugraph-cu11", marker = "extra == 'cuda-11'", specifier = ">=24.10.0" }, + { name = "cugraph-cu12", marker = "extra == 'cuda-12'", specifier = ">=24.10.0" }, + { name = "cuml-cu11", marker = "extra == 'cuda-11'", specifier = ">=24.10.0" }, + { name = "cuml-cu12", marker = "extra == 'cuda-12'", specifier = ">=24.10.0" }, { name = "esda", specifier = ">=2.7.0" }, { name = "joblib" }, { name = "lazy-loader" }, @@ -5628,8 +5662,8 @@ requires-dist = [ { name = "matplotlib" }, { name = "networkx" }, { name = "numpy", specifier = ">=2" }, - { name = "nx-cugraph-cu11", marker = "extra == 'cuda-11'", specifier = ">=24.6.0" }, - { name = "nx-cugraph-cu12", marker = "extra == 'cuda-12'", specifier = ">=24.6.0" }, + { name = "nx-cugraph-cu11", marker = "extra == 'cuda-11'", specifier = ">=24.10.0" }, + { name = "nx-cugraph-cu12", marker = "extra == 'cuda-12'", specifier = ">=24.10.0" }, { name = "pandas", specifier = ">=2" }, { name = "pysal" }, { name = "python-igraph" }, @@ -5638,7 +5672,7 @@ requires-dist = [ { name = "scipy", specifier = ">=0.16.1" }, { name = "scipy-stubs" }, { name = "seaborn" }, - { name = "spatialdata", marker = "extra == 'spatialdata'", specifier = "==0.5.0" }, + { name = "spatialdata", marker = "extra == 'spatialdata'", specifier = "==0.6.1" }, { name = "statsmodels" }, { name = "umap-learn" }, { name = "xpysom", specifier = "==1.0.7" }, @@ -5996,6 +6030,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1e/48/973da1ee8bc0743519759e74c3615b39acdc3faf00e0a0710f8c856d8c9d/statsmodels-0.14.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a085d47c8ef5387279a991633883d0e700de2b0acc812d7032d165888627bef", size = 10453538, upload-time = "2025-07-07T14:24:06.959Z" }, { url = "https://files.pythonhosted.org/packages/c7/d6/18903fb707afd31cf1edaec5201964dbdacb2bfae9a22558274647a7c88f/statsmodels-0.14.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f866b2ebb2904b47c342d00def83c526ef2eb1df6a9a3c94ba5fe63d0005aec", size = 10681584, upload-time = "2025-07-07T14:24:21.038Z" }, { url = "https://files.pythonhosted.org/packages/44/d6/80df1bbbfcdc50bff4152f43274420fa9856d56e234d160d6206eb1f5827/statsmodels-0.14.5-cp313-cp313-win_amd64.whl", hash = "sha256:2a06bca03b7a492f88c8106103ab75f1a5ced25de90103a89f3a287518017939", size = 9604641, upload-time = "2025-07-07T12:08:36.23Z" }, + { url = "https://files.pythonhosted.org/packages/fd/6c/0fb40a89d715412160097c6f3387049ed88c9bd866c8838a8852c705ae2f/statsmodels-0.14.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:07c4dad25bbb15864a31b4917a820f6d104bdc24e5ddadcda59027390c3bed9e", size = 10211256, upload-time = "2025-10-30T13:46:58.591Z" }, + { url = "https://files.pythonhosted.org/packages/88/4a/e36fe8b19270ab3e80df357da924c6c029cab0fb9a0fbd28aaf49341707d/statsmodels-0.14.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:babb067c852e966c2c933b79dbb5d0240919d861941a2ef6c0e13321c255528d", size = 10110933, upload-time = "2025-10-30T13:47:11.774Z" }, + { url = "https://files.pythonhosted.org/packages/8a/bf/1b7e7b1a6c09a88a9c5c9e60622c050dfd08af11c2e6d4a42dbc71b32ee1/statsmodels-0.14.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:110194b137286173cc676d7bad0119a197778de6478fc6cbdc3b33571165ac1e", size = 10253981, upload-time = "2025-10-30T16:32:22.399Z" }, + { url = "https://files.pythonhosted.org/packages/b8/d0/f95da95524bdd99613923ca61a3036d1308cee1290e5e8acb89f51736a8c/statsmodels-0.14.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c8a9c384a60c80731b278e7fd18764364c8817f4995b13a175d636f967823d1", size = 10460450, upload-time = "2025-10-30T16:32:44.985Z" }, + { url = "https://files.pythonhosted.org/packages/28/bb/59e7be0271be264b7b541baf3973f97747740950bfd5115de731f63da8ab/statsmodels-0.14.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:557df3a870a57248df744fdfcc444ecbc5bdbf1c042b8a8b5d8e3e797830dc2a", size = 10694060, upload-time = "2025-10-30T16:33:07.656Z" }, + { url = "https://files.pythonhosted.org/packages/8b/c0/b28d0fd0347ea38d3610052f479e4b922eb33bb8790817f93cd89e6e08ba/statsmodels-0.14.5-cp314-cp314-win_amd64.whl", hash = "sha256:95af7a9c4689d514f4341478b891f867766f3da297f514b8c4adf08f4fa61d03", size = 9648961, upload-time = "2025-10-30T13:47:24.303Z" }, ] [[package]] @@ -6357,6 +6397,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6b/b1/c24deeda9baf1fd491aaad941ed89e0fed6c583a117fd7b79e0a33a1e6c0/umap_learn-0.5.9.post2-py3-none-any.whl", hash = "sha256:fbe51166561e0e7fab00ef3d516ac2621243b8d15cf4bef9f656d701736b16a0", size = 90146, upload-time = "2025-07-03T00:18:01.042Z" }, ] +[[package]] +name = "universal-pathlib" +version = "0.3.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fsspec" }, + { name = "pathlib-abc" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/db/6874223d251a2e146dae57a27ca8cb1f71e7e135aa51ad394173ffe18fc0/universal_pathlib-0.3.6.tar.gz", hash = "sha256:d8640454ff08305fc639f7980e8bad4a7d38e82f6389ff993fb0e7b2a4969de9", size = 249113, upload-time = "2025-11-13T17:05:29.882Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/5d/fc1f5478eb486a59549e0dbea5827633bbba01139b549968d4936154b756/universal_pathlib-0.3.6-py3-none-any.whl", hash = "sha256:ff10a86e5340ad986b6f04847bb64ba397dff7467450234ffa2ab5ff135641d8", size = 78715, upload-time = "2025-11-13T17:05:28.101Z" }, +] + [[package]] name = "urllib3" version = "2.5.0" @@ -6615,17 +6668,19 @@ wheels = [ [[package]] name = "zarr" -version = "2.18.7" +version = "3.1.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "asciitree" }, - { name = "fasteners", marker = "sys_platform != 'emscripten' or (extra == 'extra-9-spatiomic-cuda-11' and extra == 'extra-9-spatiomic-cuda-12')" }, + { name = "donfig" }, + { name = "google-crc32c" }, { name = "numcodecs" }, { name = "numpy" }, + { name = "packaging" }, + { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/da/1d/01cf9e3ab2d85190278efc3fca9f68563de35ae30ee59e7640e3af98abe3/zarr-2.18.7.tar.gz", hash = "sha256:b2b8f66f14dac4af66b180d2338819981b981f70e196c9a66e6bfaa9e59572f5", size = 3604558, upload-time = "2025-04-09T07:59:28.482Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/76/7fa87f57c112c7b9c82f0a730f8b6f333e792574812872e2cd45ab604199/zarr-3.1.5.tar.gz", hash = "sha256:fbe0c79675a40c996de7ca08e80a1c0a20537bd4a9f43418b6d101395c0bba2b", size = 366825, upload-time = "2025-11-21T14:06:01.492Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5e/d8/9ffd8c237b3559945bb52103cf0eed64ea098f7b7f573f8d2962ef27b4b2/zarr-2.18.7-py3-none-any.whl", hash = "sha256:ac3dc4033e9ae4e9d7b5e27c97ea3eaf1003cc0a07f010bd83d5134bf8c4b223", size = 211273, upload-time = "2025-04-09T07:59:27.039Z" }, + { url = "https://files.pythonhosted.org/packages/44/15/bb13b4913ef95ad5448490821eee4671d0e67673342e4d4070854e5fe081/zarr-3.1.5-py3-none-any.whl", hash = "sha256:29cd905afb6235b94c09decda4258c888fcb79bb6c862ef7c0b8fe009b5c8563", size = 284067, upload-time = "2025-11-21T14:05:59.235Z" }, ] [[package]]