diff --git a/REQUIREMENTS.txt b/REQUIREMENTS.txt index 8a0a13a0c..099ae9687 100644 --- a/REQUIREMENTS.txt +++ b/REQUIREMENTS.txt @@ -12,8 +12,7 @@ mistune==0.8.4 numpy<2 read_roi regional -# scikit-image is temporarily pinned as newer versions require updating module imports -scikit-image==0.21 +scikit-image>0.22 scikit-learn seaborn semantic_version diff --git a/requirements/REQUIREMENTS-CI.txt b/requirements/REQUIREMENTS-CI.txt index 9ccf64697..2a453177a 100644 --- a/requirements/REQUIREMENTS-CI.txt +++ b/requirements/REQUIREMENTS-CI.txt @@ -1,18 +1,18 @@ # You should not edit this file directly. Instead, you should edit one of the following files (requirements/REQUIREMENTS-CI.txt.in) and run make requirements/REQUIREMENTS-CI.txt alabaster==0.7.16 asttokens==3.0.0 -attrs==24.2.0 +attrs==24.3.0 babel==2.16.0 backports.tarfile==1.2.0 beautifulsoup4==4.12.3 bleach==6.2.0 -boto3==1.35.38 -botocore==1.35.38 +boto3==1.35.86 +botocore==1.35.86 build==1.2.2.post1 -certifi==2024.8.30 +certifi==2024.12.14 cffi==1.17.1 charset-normalizer==3.4.0 -click==8.1.7 +click==8.1.8 commonmark==0.9.1 contourpy==1.3.0 coverage==7.6.9 @@ -29,10 +29,10 @@ executing==2.1.0 fastjsonschema==2.21.1 flake8==7.1.1 flake8-import-order==0.18.2 -fonttools==4.54.1 +fonttools==4.55.3 h5py==3.12.1 idna==3.10 -imageio==2.35.1 +imageio==2.36.1 imagesize==1.4.1 importlib_metadata==8.5.0 importlib_resources==6.4.5 @@ -68,20 +68,20 @@ more-itertools==10.5.0 mpmath==1.3.0 mypy==1.10.1 mypy-extensions==1.0.0 -nbclient==0.10.1 +nbclient==0.10.2 nbconvert==6.5.4 nbencdec==0.0.10 nbformat==5.10.4 networkx==3.2.1 -nh3==0.2.19 +nh3==0.2.20 numpy==1.26.4 numpydoc==1.8.0 -packaging==24.1 +packaging==24.2 pandas==2.2.3 pandocfilters==1.5.1 parso==0.8.4 pexpect==4.9.0 -pillow==10.4.0 +pillow==11.0.0 pkginfo==1.12.0 platformdirs==4.3.6 pluggy==1.5.0 @@ -92,7 +92,7 @@ pycodestyle==2.12.1 pycparser==2.22 pyflakes==3.2.0 Pygments==2.18.0 -pyparsing==3.1.4 +pyparsing==3.2.0 pyproject_hooks==1.2.0 pyrsistent==0.20.0 pytest==8.3.4 @@ -100,7 +100,6 @@ pytest-cov==6.0.0 pytest-xdist==3.6.1 python-dateutil==2.9.0.post0 pytz==2024.2 -PyWavelets==1.6.0 PyYAML==6.0.2 pyzmq==26.2.0 read-roi==1.6.0 @@ -111,16 +110,16 @@ requests==2.32.3 requests-toolbelt==1.0.0 rfc3986==2.0.0 rich==13.9.4 -s3transfer==0.10.3 -scikit-image==0.21.0 -scikit-learn==1.5.2 +s3transfer==0.10.4 +scikit-image==0.24.0 +scikit-learn==1.6.0 scipy==1.13.1 seaborn==0.13.2 SecretStorage==3.3.3 semantic-version==2.10.0 -setuptools==75.1.0 +setuptools==75.6.0 showit==1.1.4 -six==1.16.0 +six==1.17.0 slicedimage==4.1.1 snowballstemmer==2.2.0 soupsieve==2.6 @@ -145,13 +144,13 @@ tifffile==2024.8.30 tinycss2==1.4.0 tomli==2.2.1 tornado==6.4.2 -tqdm==4.66.5 +tqdm==4.67.1 trackpy==0.6.4 traitlets==5.14.3 twine==6.0.1 -types-PyYAML==6.0.12.20240917 +types-PyYAML==6.0.12.20241221 types-requests==2.31.0.6 -types-setuptools==75.6.0.20241126 +types-setuptools==75.6.0.20241223 types-urllib3==1.26.25.14 typing_extensions==4.12.2 tzdata==2024.2 @@ -160,4 +159,4 @@ validators==0.34.0 wcwidth==0.2.13 webencodings==0.5.1 xarray==2023.8.0 -zipp==3.20.2 +zipp==3.21.0 diff --git a/requirements/REQUIREMENTS-JUPYTER.txt b/requirements/REQUIREMENTS-JUPYTER.txt index aa93bcf6b..6fca459bf 100644 --- a/requirements/REQUIREMENTS-JUPYTER.txt +++ b/requirements/REQUIREMENTS-JUPYTER.txt @@ -1,24 +1,24 @@ # You should not edit this file directly. Instead, you should edit one of the following files (requirements/REQUIREMENTS-JUPYTER.txt.in) and run make requirements/REQUIREMENTS-JUPYTER.txt -anyio==4.6.0 +anyio==4.7.0 argon2-cffi==23.1.0 argon2-cffi-bindings==21.2.0 arrow==1.3.0 -asttokens==2.4.1 +asttokens==3.0.0 async-lru==2.0.4 -attrs==24.2.0 +attrs==24.3.0 babel==2.16.0 beautifulsoup4==4.12.3 -bleach==6.1.0 -boto3==1.35.38 -botocore==1.35.38 -certifi==2024.8.30 +bleach==6.2.0 +boto3==1.35.86 +botocore==1.35.86 +certifi==2024.12.14 cffi==1.17.1 charset-normalizer==3.4.0 -click==8.1.7 +click==8.1.8 comm==0.2.2 contourpy==1.3.0 cycler==0.12.1 -debugpy==1.8.7 +debugpy==1.8.11 decorator==5.1.1 defusedxml==0.7.1 diskcache==5.6.3 @@ -26,26 +26,26 @@ docutils==0.20.1 entrypoints==0.4 exceptiongroup==1.2.2 executing==2.1.0 -fastjsonschema==2.20.0 -fonttools==4.54.1 +fastjsonschema==2.21.1 +fonttools==4.55.3 fqdn==1.5.1 h11==0.14.0 h5py==3.12.1 -httpcore==1.0.6 -httpx==0.27.2 +httpcore==1.0.7 +httpx==0.28.1 idna==3.10 -imageio==2.35.1 +imageio==2.36.1 importlib_metadata==8.5.0 importlib_resources==6.4.5 ipykernel==6.29.5 ipython==8.18.1 ipywidgets==8.1.5 isoduration==20.11.0 -jedi==0.19.1 +jedi==0.19.2 Jinja2==3.1.5 jmespath==1.0.1 joblib==1.4.2 -json5==0.9.25 +json5==0.10.0 jsonpointer==3.0.0 jsonschema==4.17.3 jupyter==1.1.1 @@ -64,12 +64,12 @@ kiwisolver==1.4.7 lazy_loader==0.4 looseversion==1.3.0 lxml==5.3.0 -MarkupSafe==3.0.1 +MarkupSafe==3.0.2 matplotlib==3.7.5 matplotlib-inline==0.1.7 mistune==0.8.4 mpmath==1.3.0 -nbclient==0.10.0 +nbclient==0.10.2 nbconvert==6.5.4 nbformat==5.10.4 nest-asyncio==1.6.0 @@ -78,26 +78,25 @@ notebook==7.1.3 notebook_shim==0.2.4 numpy==1.26.4 overrides==7.7.0 -packaging==24.1 +packaging==24.2 pandas==2.2.3 pandocfilters==1.5.1 parso==0.8.4 pexpect==4.9.0 -pillow==10.4.0 +pillow==11.0.0 platformdirs==4.3.6 -prometheus_client==0.21.0 +prometheus_client==0.21.1 prompt_toolkit==3.0.48 -psutil==6.0.0 +psutil==6.1.1 ptyprocess==0.7.0 pure_eval==0.2.3 pycparser==2.22 Pygments==2.18.0 -pyparsing==3.1.4 +pyparsing==3.2.0 pyrsistent==0.20.0 python-dateutil==2.9.0.post0 -python-json-logger==2.0.7 +python-json-logger==3.2.1 pytz==2024.2 -PyWavelets==1.6.0 PyYAML==6.0.2 pyzmq==26.2.0 read-roi==1.6.0 @@ -105,16 +104,16 @@ regional==1.1.2 requests==2.32.3 rfc3339-validator==0.1.4 rfc3986-validator==0.1.1 -s3transfer==0.10.3 -scikit-image==0.21.0 -scikit-learn==1.5.2 +s3transfer==0.10.4 +scikit-image==0.24.0 +scikit-learn==1.6.0 scipy==1.13.1 seaborn==0.13.2 semantic-version==2.10.0 Send2Trash==1.8.3 -setuptools==75.1.0 +setuptools==75.6.0 showit==1.1.4 -six==1.16.0 +six==1.17.0 slicedimage==4.1.1 sniffio==1.3.1 soupsieve==2.6 @@ -123,22 +122,22 @@ sympy==1.13.3 terminado==0.18.1 threadpoolctl==3.5.0 tifffile==2024.8.30 -tinycss2==1.3.0 -tomli==2.0.2 +tinycss2==1.4.0 +tomli==2.2.1 tornado==6.4.2 -tqdm==4.66.5 +tqdm==4.67.1 trackpy==0.6.4 traitlets==5.14.3 -types-python-dateutil==2.9.0.20241003 +types-python-dateutil==2.9.0.20241206 typing_extensions==4.12.2 tzdata==2024.2 uri-template==1.3.0 urllib3==1.26.20 validators==0.34.0 wcwidth==0.2.13 -webcolors==24.8.0 +webcolors==24.11.1 webencodings==0.5.1 websocket-client==1.8.0 widgetsnbextension==4.0.13 xarray==2023.8.0 -zipp==3.20.2 +zipp==3.21.0 diff --git a/requirements/REQUIREMENTS-NAPARI-CI.txt b/requirements/REQUIREMENTS-NAPARI-CI.txt index 864f9b440..8890f6257 100644 --- a/requirements/REQUIREMENTS-NAPARI-CI.txt +++ b/requirements/REQUIREMENTS-NAPARI-CI.txt @@ -1,25 +1,25 @@ # You should not edit this file directly. Instead, you should edit one of the following files (requirements/REQUIREMENTS-NAPARI-CI.txt.in) and run make requirements/REQUIREMENTS-NAPARI-CI.txt alabaster==0.7.16 annotated-types==0.7.0 -app-model==0.3.0 +app-model==0.3.1 appdirs==1.4.4 asciitree==0.3.3 -asttokens==2.4.1 -attrs==24.2.0 +asttokens==3.0.0 +attrs==24.3.0 babel==2.16.0 -boto3==1.35.38 -botocore==1.35.38 +boto3==1.35.86 +botocore==1.35.86 build==1.2.2.post1 cachey==0.2.1 -certifi==2024.8.30 +certifi==2024.12.14 charset-normalizer==3.4.0 -click==8.1.7 -cloudpickle==3.0.0 +click==8.1.8 +cloudpickle==3.1.0 comm==0.2.2 contourpy==1.3.0 cycler==0.12.1 dask==2024.8.0 -debugpy==1.8.7 +debugpy==1.8.11 decorator==5.1.1 diskcache==5.6.3 docstring_parser==0.16 @@ -28,15 +28,15 @@ exceptiongroup==1.2.2 executing==2.1.0 fasteners==0.19 flexcache==0.3 -flexparser==0.3.1 -fonttools==4.54.1 +flexparser==0.4 +fonttools==4.55.3 freetype-py==2.5.1 -fsspec==2024.9.0 +fsspec==2024.12.0 h5py==3.12.1 HeapDict==1.0.1 hsluv==5.0.4 idna==3.10 -imageio==2.35.1 +imageio==2.36.1 imagesize==1.4.1 importlib_metadata==8.5.0 importlib_resources==6.4.5 @@ -44,7 +44,7 @@ in-n-out==0.2.1 iniconfig==2.0.0 ipykernel==6.29.5 ipython==8.18.1 -jedi==0.19.1 +jedi==0.19.2 Jinja2==3.1.5 jmespath==1.0.1 joblib==1.4.2 @@ -56,16 +56,16 @@ lazy_loader==0.4 llvmlite==0.43.0 locket==1.0.0 looseversion==1.3.0 -magicgui==0.9.1 +magicgui==0.10.0 markdown-it-py==3.0.0 -MarkupSafe==3.0.1 +MarkupSafe==3.0.2 matplotlib==3.7.5 matplotlib-inline==0.1.7 mdurl==0.1.2 mistune==0.8.4 mpmath==1.3.0 -napari==0.5.4 -napari-console==0.1.0 +napari==0.5.5 +napari-console==0.1.3 napari-plugin-engine==0.2.0 napari-plugin-manager==0.1.3 napari-svg==0.2.0 @@ -76,56 +76,55 @@ numba==0.60.0 numcodecs==0.12.1 numpy==1.26.4 numpydoc==1.8.0 -packaging==24.1 +packaging==24.2 pandas==2.2.3 parso==0.8.4 partd==1.4.2 pexpect==4.9.0 -pillow==10.4.0 -Pint==0.24.3 +pillow==11.0.0 +Pint==0.24.4 platformdirs==4.3.6 pluggy==1.5.0 pooch==1.8.2 prompt_toolkit==3.0.48 -psutil==6.0.0 +psutil==6.1.1 psygnal==0.11.1 ptyprocess==0.7.0 pure_eval==0.2.3 pyconify==0.1.6 -pydantic==2.9.2 +pydantic==2.10.4 pydantic-compat==0.1.2 -pydantic_core==2.23.4 +pydantic_core==2.27.2 Pygments==2.18.0 PyOpenGL==3.1.7 -pyparsing==3.1.4 +pyparsing==3.2.0 pyproject_hooks==1.2.0 PyQt5==5.15.11 -PyQt5-Qt5==5.15.15 -PyQt5_sip==12.15.0 +PyQt5-Qt5==5.15.16 +PyQt5_sip==12.16.1 pyrsistent==0.20.0 -pytest==8.3.3 +pytest==8.3.4 pytest-qt==4.4.0 python-dateutil==2.9.0.post0 pytz==2024.2 -PyWavelets==1.6.0 PyYAML==6.0.2 pyzmq==26.2.0 -qtconsole==5.6.0 -QtPy==2.4.1 +qtconsole==5.6.1 +QtPy==2.4.2 read-roi==1.6.0 regional==1.1.2 requests==2.32.3 -rich==13.9.2 -s3transfer==0.10.3 -scikit-image==0.21.0 -scikit-learn==1.5.2 +rich==13.9.4 +s3transfer==0.10.4 +scikit-image==0.24.0 +scikit-learn==1.6.0 scipy==1.13.1 seaborn==0.13.2 semantic-version==2.10.0 -setuptools==75.1.0 +setuptools==75.6.0 shellingham==1.5.4 showit==1.1.4 -six==1.16.0 +six==1.17.0 slicedimage==4.1.1 snowballstemmer==2.2.0 Sphinx==7.4.7 @@ -136,27 +135,27 @@ sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==2.0.0 sphinxcontrib-serializinghtml==2.0.0 stack-data==0.6.3 -superqt==0.6.7 +superqt==0.7.0 sympy==1.13.3 tabulate==0.9.0 threadpoolctl==3.5.0 tifffile==2024.8.30 -tomli==2.0.2 +tomli==2.2.1 tomli_w==1.1.0 toolz==1.0.0 tornado==6.4.2 -tqdm==4.66.5 +tqdm==4.67.1 trackpy==0.6.4 traitlets==5.14.3 triangle==20230923 -typer==0.12.5 +typer==0.15.1 typing_extensions==4.12.2 tzdata==2024.2 urllib3==1.26.20 validators==0.34.0 vispy==0.14.3 wcwidth==0.2.13 -wrapt==1.16.0 +wrapt==1.17.0 xarray==2023.8.0 zarr==2.18.2 -zipp==3.20.2 +zipp==3.21.0 diff --git a/starfish/REQUIREMENTS-STRICT.txt b/starfish/REQUIREMENTS-STRICT.txt index 1e3a4d041..f4db58a88 100644 --- a/starfish/REQUIREMENTS-STRICT.txt +++ b/starfish/REQUIREMENTS-STRICT.txt @@ -1,18 +1,18 @@ # You should not edit this file directly. Instead, you should edit one of the following files (REQUIREMENTS.txt) and run make starfish/REQUIREMENTS-STRICT.txt -attrs==24.2.0 -boto3==1.35.38 -botocore==1.35.38 -certifi==2024.8.30 +attrs==24.3.0 +boto3==1.35.86 +botocore==1.35.86 +certifi==2024.12.14 charset-normalizer==3.4.0 -click==8.1.7 +click==8.1.8 contourpy==1.3.0 cycler==0.12.1 diskcache==5.6.3 docutils==0.20.1 -fonttools==4.54.1 +fonttools==4.55.3 h5py==3.12.1 idna==3.10 -imageio==2.35.1 +imageio==2.36.1 importlib_resources==6.4.5 jmespath==1.0.1 joblib==1.4.2 @@ -25,35 +25,34 @@ mistune==0.8.4 mpmath==1.3.0 networkx==3.2.1 numpy==1.26.4 -packaging==24.1 +packaging==24.2 pandas==2.2.3 -pillow==10.4.0 -pyparsing==3.1.4 +pillow==11.0.0 +pyparsing==3.2.0 pyrsistent==0.20.0 python-dateutil==2.9.0.post0 pytz==2024.2 -PyWavelets==1.6.0 PyYAML==6.0.2 read-roi==1.6.0 regional==1.1.2 requests==2.32.3 -s3transfer==0.10.3 -scikit-image==0.21.0 -scikit-learn==1.5.2 +s3transfer==0.10.4 +scikit-image==0.24.0 +scikit-learn==1.6.0 scipy==1.13.1 seaborn==0.13.2 semantic-version==2.10.0 -setuptools==75.1.0 +setuptools==75.6.0 showit==1.1.4 -six==1.16.0 +six==1.17.0 slicedimage==4.1.1 sympy==1.13.3 threadpoolctl==3.5.0 tifffile==2024.8.30 -tqdm==4.66.5 +tqdm==4.67.1 trackpy==0.6.4 tzdata==2024.2 urllib3==1.26.20 validators==0.34.0 xarray==2023.8.0 -zipp==3.20.2 +zipp==3.21.0 diff --git a/starfish/core/compat.py b/starfish/core/compat.py deleted file mode 100644 index 9133b6b61..000000000 --- a/starfish/core/compat.py +++ /dev/null @@ -1,410 +0,0 @@ -import skimage -from packaging import version - -if version.parse(skimage.__version__) >= version.parse("0.16.0"): - import skimage.exposure - match_histograms = skimage.exposure.match_histograms -elif version.parse("0.16.0") > version.parse(skimage.__version__) > version.parse("0.14.2"): - import skimage.transform - match_histograms = skimage.transform.match_histograms -else: - - """ - Unless otherwise specified by LICENSE.txt files in individual - directories, all code is - - Copyright (C) 2011, the scikit-image team - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 3. Neither the name of skimage nor the names of its contributors may be - used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS`` AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - """ - - import numpy as np - - def _match_cumulative_cdf(source, template): - """ - Return modified source array so that the cumulative density function of - its values matches the cumulative density function of the template. - """ - src_values, src_unique_indices, src_counts = np.unique( - source.ravel(), return_inverse=True, return_counts=True) - tmpl_values, tmpl_counts = np.unique(template.ravel(), return_counts=True) - - # calculate normalized quantiles for each array - src_quantiles = np.cumsum(src_counts) / source.size - tmpl_quantiles = np.cumsum(tmpl_counts) / template.size - - interp_a_values = np.interp(src_quantiles, tmpl_quantiles, tmpl_values) - return interp_a_values[src_unique_indices].reshape(source.shape) - - def match_histograms(image, reference, multichannel=False): - """ - Adjust an image so that its cumulative histogram matches that of another. - The adjustment is applied separately for each channel. - - Parameters - ---------- - image : ndarray - Input image. Can be gray-scale or in color. - reference : ndarray - Image to match histogram of. Must have the same number of channels as - image. - multichannel : bool, optional - Apply the matching separately for each channel. - - Returns - ------- - matched : ndarray - Transformed input image. - - Raises - ------ - ValueError - Thrown when the number of channels in the input image and the reference - differ. - - References - ---------- - .. [1] http://paulbourke.net/miscellaneous/equalisation/ - """ - if image.ndim != reference.ndim: - raise ValueError('Image and reference must have the same number of channels.') - - if multichannel: - if image.shape[-1] != reference.shape[-1]: - raise ValueError('Number of channels in the input image and reference ' - 'image must match!') - - matched = np.empty(image.shape, dtype=image.dtype) - for channel in range(image.shape[-1]): - matched_channel = _match_cumulative_cdf( - image[..., channel], reference[..., channel]) - matched[..., channel] = matched_channel - else: - matched = _match_cumulative_cdf(image, reference) - - return matched - -if version.parse(skimage.__version__) > version.parse("0.14.2"): - import skimage.feature - blob_log = skimage.feature.blob_log - blob_dog = skimage.feature.blob_dog -else: - from skimage.feature.blob import _prune_blobs - import numpy as np - from scipy.ndimage import gaussian_filter, gaussian_laplace - from skimage import img_as_float - from skimage.feature import peak_local_max - - def blob_dog(image, min_sigma=1, max_sigma=50, sigma_ratio=1.6, threshold=2.0, - overlap=.5, *, exclude_border=False): - """ - Finds blobs in the given grayscale image. - Blobs are found using the Difference of Gaussian (DoG) method [1]_. - For each blob found, the method returns its coordinates and the standard - deviation of the Gaussian kernel that detected the blob. - - Parameters - ---------- - image : 2D or 3D ndarray - Input grayscale image, blobs are assumed to be light on dark - background (white on black). - min_sigma : scalar or sequence of scalars, optional - The minimum standard deviation for Gaussian kernel. Keep this low to - detect smaller blobs. The standard deviations of the Gaussian filter - are given for each axis as a sequence, or as a single number, in - which case it is equal for all axes. - max_sigma : scalar or sequence of scalars, optional - The maximum standard deviation for Gaussian kernel. Keep this high to - detect larger blobs. The standard deviations of the Gaussian filter - are given for each axis as a sequence, or as a single number, in - which case it is equal for all axes. - sigma_ratio : float, optional - The ratio between the standard deviation of Gaussian Kernels used for - computing the Difference of Gaussians - threshold : float, optional. - The absolute lower bound for scale space maxima. Local maxima smaller - than thresh are ignored. Reduce this to detect blobs with less - intensities. - overlap : float, optional - A value between 0 and 1. If the area of two blobs overlaps by a - fraction greater than `threshold`, the smaller blob is eliminated. - exclude_border : int or bool, optional - If nonzero int, `exclude_border` excludes blobs from - within `exclude_border`-pixels of the border of the image. - - Returns - ------- - A : (n, image.ndim + sigma) ndarray - A 2d array with each row representing 2 coordinate values for a 2D - image, and 3 coordinate values for a 3D image, plus the sigma(s) used. - When a single sigma is passed, outputs are: - ``(r, c, sigma)`` or ``(p, r, c, sigma)`` where ``(r, c)`` or - ``(p, r, c)`` are coordinates of the blob and ``sigma`` is the standard - deviation of the Gaussian kernel which detected the blob. When an - anisotropic gaussian is used (sigmas per dimension), the detected sigma - is returned for each dimension. - - References - ---------- - [1] https://en.wikipedia.org/wiki/Blob_detection#The_difference_of_Gaussians_approach - - Examples - -------- - >>> from skimage import data, feature - >>> feature.blob_dog(data.coins(), threshold=.5, max_sigma=40) - array([[ 267. , 359. , 16.777216], - [ 267. , 115. , 10.48576 ], - [ 263. , 302. , 16.777216], - [ 263. , 245. , 16.777216], - [ 261. , 173. , 16.777216], - [ 260. , 46. , 16.777216], - [ 198. , 155. , 10.48576 ], - [ 196. , 43. , 10.48576 ], - [ 195. , 102. , 16.777216], - [ 194. , 277. , 16.777216], - [ 193. , 213. , 16.777216], - [ 185. , 347. , 16.777216], - [ 128. , 154. , 10.48576 ], - [ 127. , 102. , 10.48576 ], - [ 125. , 208. , 10.48576 ], - [ 125. , 45. , 16.777216], - [ 124. , 337. , 10.48576 ], - [ 120. , 272. , 16.777216], - [ 58. , 100. , 10.48576 ], - [ 54. , 276. , 10.48576 ], - [ 54. , 42. , 16.777216], - [ 52. , 216. , 16.777216], - [ 52. , 155. , 16.777216], - [ 45. , 336. , 16.777216]]) - - Notes - ----- - The radius of each blob is approximately :math:`sqrt{2}sigma` for - a 2-D image and :math:`sqrt{3}sigma` for a 3-D image. - """ - - image = img_as_float(image) - - # if both min and max sigma are scalar, function returns only one sigma - scalar_sigma = np.isscalar(max_sigma) and np.isscalar(min_sigma) - - # Gaussian filter requires that sequence-type sigmas have same - # dimensionality as image. This broadcasts scalar kernels - if np.isscalar(max_sigma): - max_sigma = np.full(image.ndim, max_sigma, dtype=float) - if np.isscalar(min_sigma): - min_sigma = np.full(image.ndim, min_sigma, dtype=float) - - # Convert sequence types to array - min_sigma = np.asarray(min_sigma, dtype=float) - max_sigma = np.asarray(max_sigma, dtype=float) - - # k such that min_sigma*(sigma_ratio**k) > max_sigma - k = int(np.mean(np.log(max_sigma / min_sigma) / np.log(sigma_ratio) + 1)) - - # a geometric progression of standard deviations for gaussian kernels - sigma_list = np.array([min_sigma * (sigma_ratio ** i) - for i in range(k + 1)]) - - gaussian_images = [gaussian_filter(image, s) for s in sigma_list] - - # computing difference between two successive Gaussian blurred images - # multiplying with average standard deviation provides scale invariance - dog_images = [(gaussian_images[i] - gaussian_images[i + 1]) - * np.mean(sigma_list[i]) for i in range(k)] - - image_cube = np.stack(dog_images, axis=-1) - - # local_maxima = get_local_maxima(image_cube, threshold) - local_maxima = peak_local_max(image_cube, threshold_abs=threshold, - footprint=np.ones((3,) * (image.ndim + 1)), - threshold_rel=0.0, - exclude_border=exclude_border) - # Catch no peaks - if local_maxima.size == 0: - return np.empty((0, 3)) - - # Convert local_maxima to float64 - lm = local_maxima.astype(np.float64) - - # translate final column of lm, which contains the index of the - # sigma that produced the maximum intensity value, into the sigma - sigmas_of_peaks = sigma_list[local_maxima[:, -1]] - - if scalar_sigma: - # select one sigma column, keeping dimension - sigmas_of_peaks = sigmas_of_peaks[:, 0:1] - - # Remove sigma index and replace with sigmas - lm = np.hstack([lm[:, :-1], sigmas_of_peaks]) - - return _prune_blobs(lm, overlap) - - def blob_log(image, min_sigma=1, max_sigma=50, num_sigma=10, threshold=.2, - overlap=.5, log_scale=False, *, exclude_border=False): - """ - Finds blobs in the given grayscale image. - Blobs are found using the Laplacian of Gaussian (LoG) method [1]_. - For each blob found, the method returns its coordinates and the standard - deviation of the Gaussian kernel that detected the blob. - - Parameters - ---------- - image : 2D or 3D ndarray - Input grayscale image, blobs are assumed to be light on dark - background (white on black). - min_sigma : scalar or sequence of scalars, optional - the minimum standard deviation for Gaussian kernel. Keep this low to - detect smaller blobs. The standard deviations of the Gaussian filter - are given for each axis as a sequence, or as a single number, in - which case it is equal for all axes. - max_sigma : scalar or sequence of scalars, optional - The maximum standard deviation for Gaussian kernel. Keep this high to - detect larger blobs. The standard deviations of the Gaussian filter - are given for each axis as a sequence, or as a single number, in - which case it is equal for all axes. - num_sigma : int, optional - The number of intermediate values of standard deviations to consider - between `min_sigma` and `max_sigma`. - threshold : float, optional. - The absolute lower bound for scale space maxima. Local maxima smaller - than thresh are ignored. Reduce this to detect blobs with less - intensities. - overlap : float, optional - A value between 0 and 1. If the area of two blobs overlaps by a - fraction greater than `threshold`, the smaller blob is eliminated. - log_scale : bool, optional - If set intermediate values of standard deviations are interpolated - using a logarithmic scale to the base `10`. If not, linear - interpolation is used. - exclude_border : int or bool, optional - If nonzero int, `exclude_border` excludes blobs from - within `exclude_border`-pixels of the border of the image. - - Returns - ------- - A : (n, image.ndim + sigma) ndarray - A 2d array with each row representing 2 coordinate values for a 2D - image, and 3 coordinate values for a 3D image, plus the sigma(s) used. - When a single sigma is passed, outputs are: - ``(r, c, sigma)`` or ``(p, r, c, sigma)`` where ``(r, c)`` or - ``(p, r, c)`` are coordinates of the blob and ``sigma`` is the standard - deviation of the Gaussian kernel which detected the blob. When an - anisotropic gaussian is used (sigmas per dimension), the detected sigma - is returned for each dimension. - - References - ---------- - .. [1] https://en.wikipedia.org/wiki/Blob_detection#The_Laplacian_of_Gaussian - - Examples - -------- - >>> from skimage import data, feature, exposure - >>> img = data.coins() - >>> img = exposure.equalize_hist(img) # improves detection - >>> feature.blob_log(img, threshold = .3) - array([[ 266. , 115. , 11.88888889], - [ 263. , 302. , 17.33333333], - [ 263. , 244. , 17.33333333], - [ 260. , 174. , 17.33333333], - [ 198. , 155. , 11.88888889], - [ 198. , 103. , 11.88888889], - [ 197. , 44. , 11.88888889], - [ 194. , 276. , 17.33333333], - [ 194. , 213. , 17.33333333], - [ 185. , 344. , 17.33333333], - [ 128. , 154. , 11.88888889], - [ 127. , 102. , 11.88888889], - [ 126. , 208. , 11.88888889], - [ 126. , 46. , 11.88888889], - [ 124. , 336. , 11.88888889], - [ 121. , 272. , 17.33333333], - [ 113. , 323. , 1. ]]) - - Notes - ----- - The radius of each blob is approximately :math:`sqrt{2}sigma` for - a 2-D image and :math:`sqrt{3}sigma` for a 3-D image. - """ - image = img_as_float(image) - - # if both min and max sigma are scalar, function returns only one sigma - scalar_sigma = ( - True if np.isscalar(max_sigma) and np.isscalar(min_sigma) else False - ) - - # Gaussian filter requires that sequence-type sigmas have same - # dimensionality as image. This broadcasts scalar kernels - if np.isscalar(max_sigma): - max_sigma = np.full(image.ndim, max_sigma, dtype=float) - if np.isscalar(min_sigma): - min_sigma = np.full(image.ndim, min_sigma, dtype=float) - - # Convert sequence types to array - min_sigma = np.asarray(min_sigma, dtype=float) - max_sigma = np.asarray(max_sigma, dtype=float) - - if log_scale: - start, stop = np.log10(min_sigma)[:, None], np.log10(max_sigma)[:, None] - space = np.concatenate( - [start, stop, np.full_like(start, num_sigma)], axis=1) - sigma_list = np.stack([np.logspace(*s) for s in space], axis=1) - else: - scale = np.linspace(0, 1, num_sigma)[:, None] - sigma_list = scale * (max_sigma - min_sigma) + min_sigma - - # computing gaussian laplace - # average s**2 provides scale invariance - gl_images = [-gaussian_laplace(image, s) * s ** 2 - for s in np.mean(sigma_list, axis=1)] - - image_cube = np.stack(gl_images, axis=-1) - - local_maxima = peak_local_max(image_cube, threshold_abs=threshold, - footprint=np.ones((3,) * (image.ndim + 1)), - threshold_rel=0.0, - exclude_border=exclude_border) - - # Catch no peaks - if local_maxima.size == 0: - return np.empty((0, 3)) - - # Convert local_maxima to float64 - lm = local_maxima.astype(np.float64) - - # translate final column of lm, which contains the index of the - # sigma that produced the maximum intensity value, into the sigma - sigmas_of_peaks = sigma_list[local_maxima[:, -1]] - - if scalar_sigma: - # select one sigma column, keeping dimension - sigmas_of_peaks = sigmas_of_peaks[:, 0:1] - - # Remove sigma index and replace with sigmas - lm = np.hstack([lm[:, :-1], sigmas_of_peaks]) - - return _prune_blobs(lm, overlap) diff --git a/starfish/core/experiment/builder/test/factories/unique_tiles.py b/starfish/core/experiment/builder/test/factories/unique_tiles.py index 90d149373..9fb21025b 100644 --- a/starfish/core/experiment/builder/test/factories/unique_tiles.py +++ b/starfish/core/experiment/builder/test/factories/unique_tiles.py @@ -2,7 +2,7 @@ from typing import Mapping import numpy as np -from skimage import img_as_float32 +from skimage.util import img_as_float32 from slicedimage import ImageFormat from starfish.core.types import Axes diff --git a/starfish/core/image/Filter/gaussian_low_pass.py b/starfish/core/image/Filter/gaussian_low_pass.py index 77e4b7d5a..501a94ec3 100644 --- a/starfish/core/image/Filter/gaussian_low_pass.py +++ b/starfish/core/image/Filter/gaussian_low_pass.py @@ -84,7 +84,7 @@ def _low_pass( filtered = gaussian( image, - sigma=sigma, output=None, cval=0, channel_axis=None, preserve_range=True, truncate=4.0 + sigma=sigma, out=None, cval=0, channel_axis=None, preserve_range=True, truncate=4.0 ) return filtered diff --git a/starfish/core/image/Filter/match_histograms.py b/starfish/core/image/Filter/match_histograms.py index ab362859f..190961ddb 100644 --- a/starfish/core/image/Filter/match_histograms.py +++ b/starfish/core/image/Filter/match_histograms.py @@ -3,8 +3,8 @@ import numpy as np import xarray as xr +from skimage.exposure import match_histograms -from starfish.core.compat import match_histograms from starfish.core.imagestack.imagestack import ImageStack from starfish.core.types import Axes from starfish.core.util import enum diff --git a/starfish/core/image/_registration/transforms_list.py b/starfish/core/image/_registration/transforms_list.py index d65e1ccfb..0d16f12a8 100644 --- a/starfish/core/image/_registration/transforms_list.py +++ b/starfish/core/image/_registration/transforms_list.py @@ -3,7 +3,7 @@ import numpy as np from semantic_version import Version -from skimage.transform._geometric import _GeometricTransform, SimilarityTransform +from skimage.transform._geometric import SimilarityTransform from slicedimage.io import resolve_path_or_url from starfish.core.config import StarfishConfig @@ -28,17 +28,17 @@ class TransformsList: def __init__(self, transforms_list: Optional[List[Tuple[Mapping[Axes, int], TransformType, - _GeometricTransform]]] = None + SimilarityTransform]]] = None ): """ Parameters ---------- - transforms_list: List[Tuple[Mapping[Axes, int], TransformType, _GeometricTransform]] + transforms_list: List[Tuple[Mapping[Axes, int], TransformType, SimilarityTransform]] A list of tuples containing axes of an Imagestack and associated transform to apply. """ - self.transforms: List[Tuple[Mapping[Axes, int], TransformType, _GeometricTransform]] + self.transforms: List[Tuple[Mapping[Axes, int], TransformType, SimilarityTransform]] if transforms_list: self.transforms = transforms_list else: @@ -55,10 +55,10 @@ def __repr__(self) -> str: def append(self, selectors: Mapping[Axes, int], transform_type: TransformType, - transform_object: _GeometricTransform + transform_object: SimilarityTransform ) -> None: """ - Adds a new GoemetricTransform object to the list + Adds a new SimilarityTransform object to the list Parameters ---------- @@ -136,7 +136,7 @@ def from_dict(cls, transforms_document: dict) -> "TransformsList": transforms_list: List[Tuple[Mapping[Axes, int], TransformType, - _GeometricTransform]] = list() + SimilarityTransform]] = list() for selectors_str, transform_type_str, transforms_matrix in transforms_array: selectors = {Axes(k): v for k, v in selectors_str.items()} transform_type = TransformType(transform_type_str) diff --git a/starfish/core/imagestack/imagestack.py b/starfish/core/imagestack/imagestack.py index c2545af43..3df8812f1 100644 --- a/starfish/core/imagestack/imagestack.py +++ b/starfish/core/imagestack/imagestack.py @@ -30,7 +30,7 @@ import pandas as pd import skimage.io import xarray as xr -from skimage import img_as_float32 +from skimage.util import img_as_float32 from slicedimage import ( ImageFormat, Reader, diff --git a/starfish/core/imagestack/test/test_slicedimage_dtype.py b/starfish/core/imagestack/test/test_slicedimage_dtype.py index 99f489c04..a9ae802ae 100644 --- a/starfish/core/imagestack/test/test_slicedimage_dtype.py +++ b/starfish/core/imagestack/test/test_slicedimage_dtype.py @@ -3,7 +3,7 @@ import numpy as np import pytest -from skimage import img_as_float32 +from skimage.util import img_as_float32 from slicedimage import ImageFormat from starfish.core.errors import DataFormatWarning diff --git a/starfish/core/spots/FindSpots/blob.py b/starfish/core/spots/FindSpots/blob.py index e468f73b5..82b3ebc5e 100644 --- a/starfish/core/spots/FindSpots/blob.py +++ b/starfish/core/spots/FindSpots/blob.py @@ -128,7 +128,7 @@ def image_to_spots( fitted_blobs_array: np.ndarray = self.detector_method( data_image, **spot_finding_args - ) + ) # type: ignore # error: Cannot call function of unknown type [operator] if fitted_blobs_array.shape[0] == 0: empty_spot_attrs = SpotAttributes.empty( diff --git a/starfish/core/test/factories.py b/starfish/core/test/factories.py index 1554700dc..e2f946fc4 100644 --- a/starfish/core/test/factories.py +++ b/starfish/core/test/factories.py @@ -4,7 +4,7 @@ import numpy as np from scipy.ndimage import gaussian_filter -from skimage import img_as_float32, img_as_uint +from skimage.util import img_as_float32, img_as_uint from starfish import Codebook, ImageStack, IntensityTable from starfish.core.image.Filter.white_tophat import WhiteTophat