From 8b47b4c1d9063841f8bee0a9ee4a7f738ef54c6f Mon Sep 17 00:00:00 2001 From: keejkrej Date: Tue, 17 Feb 2026 13:50:24 +0000 Subject: [PATCH 1/5] refactor: lazy imports for nifty, vigra, elf.io - Move nifty.tools blocking import inside functions that use it - Move vigra import inside get_centers_and_bounding_boxes - Move elf.io open_file import inside load_image_data - Avoids import errors when optional deps not installed Co-authored-by: Cursor --- micro_sam/prompt_based_segmentation.py | 5 +++-- micro_sam/util.py | 23 ++++++++++++----------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/micro_sam/prompt_based_segmentation.py b/micro_sam/prompt_based_segmentation.py index 7e38ae063..82dbfcb89 100644 --- a/micro_sam/prompt_based_segmentation.py +++ b/micro_sam/prompt_based_segmentation.py @@ -12,8 +12,6 @@ import torch -from nifty.tools import blocking - from segment_anything.predictor import SamPredictor from segment_anything.utils.transforms import ResizeLongestSide @@ -155,6 +153,7 @@ def _process_box(box, shape, original_size=None, box_extension=0): # and bring the points to the coordinate system of the tile. # Discard points that are not in the tile and warn if this happens. def _points_to_tile(prompts, shape, tile_shape, halo): + from nifty.tools import blocking points, labels = prompts tiling = blocking([0, 0], shape, tile_shape) @@ -186,6 +185,7 @@ def _points_to_tile(prompts, shape, tile_shape, halo): def _box_to_tile(box, shape, tile_shape, halo): + from nifty.tools import blocking tiling = blocking([0, 0], shape, tile_shape) center = np.array([(box[0] + box[2]) / 2, (box[1] + box[3]) / 2]).round().astype("int").tolist() tile_id = tiling.coordinatesToBlockId(center) @@ -205,6 +205,7 @@ def _box_to_tile(box, shape, tile_shape, halo): def _mask_to_tile(mask, shape, tile_shape, halo): + from nifty.tools import blocking tiling = blocking([0, 0], shape, tile_shape) coords = np.where(mask) diff --git a/micro_sam/util.py b/micro_sam/util.py index 531e741d0..81bb14593 100644 --- a/micro_sam/util.py +++ b/micro_sam/util.py @@ -8,25 +8,20 @@ import hashlib import warnings from concurrent import futures +from concurrent import futures from pathlib import Path from collections import OrderedDict from typing import Any, Dict, Iterable, List, Optional, Tuple, Union, Callable -import elf.parallel as parallel_impl -import imageio.v3 as imageio -import numpy as np -import pooch -import segment_anything.utils.amg as amg_utils +import zarr import torch -import vigra +import pooch import xxhash -import zarr - -from elf.io import open_file -from nifty.tools import blocking +import numpy as np +import imageio.v3 as imageio +import segment_anything.utils.amg as amg_utils from skimage.measure import regionprops from skimage.segmentation import relabel_sequential -from torchvision.ops.boxes import batched_nms from .__version__ import __version__ from . import models as custom_models @@ -762,6 +757,7 @@ def _check_mask(tile_id): def _compute_tiled_features_2d(predictor, input_, tile_shape, halo, f, pbar_init, pbar_update, batch_size, mask): + from nifty.tools import blocking tiling = blocking([0, 0], input_.shape[:2], tile_shape) n_tiles = tiling.numberOfBlocks @@ -850,6 +846,7 @@ def __next__(self): def _compute_tiled_features_3d(predictor, input_, tile_shape, halo, f, pbar_init, pbar_update, batch_size, mask): + from nifty.tools import blocking assert input_.ndim == 3 shape = input_.shape[1:] @@ -1301,6 +1298,7 @@ def get_centers_and_bounding_boxes( if mode == "p": center_coordinates = {prop.label: prop.centroid for prop in properties} elif mode == "v": + import vigra center_coordinates = vigra.filters.eccentricityCenters(segmentation.astype('float32')) center_coordinates = {i: coord for i, coord in enumerate(center_coordinates) if i > 0} @@ -1324,6 +1322,7 @@ def load_image_data(path: str, key: Optional[str] = None, lazy_loading: bool = F if key is None: image_data = imageio.imread(path) else: + from elf.io import open_file with open_file(path, mode="r") as f: image_data = f[key] if not lazy_loading: @@ -1807,6 +1806,7 @@ def require_numpy(mask): segmentation[this_mask] = this_seg_id seg_id = this_seg_id + 1 + import elf.parallel as parallel_impl block_shape = (512, 512) if label_masks: segmentation_cc = np.zeros_like(segmentation, dtype=segmentation.dtype) @@ -1889,6 +1889,7 @@ def apply_nms( scores = data["iou_preds"] * data["stability_scores"] boxes = _xywh_to_xyxy(data["global_boxes"] if is_tiled else data["boxes"]) if perform_box_nms: + from torchvision.ops.boxes import batched_nms assert not intersection_over_min # not implemented keep_by_nms = batched_nms( boxes, From c257f09b42630cb625762ed2249dbb4bb08db75b Mon Sep 17 00:00:00 2001 From: keejkrej Date: Tue, 17 Feb 2026 15:06:53 +0000 Subject: [PATCH 2/5] fix: remove duplicate concurrent.futures import Co-authored-by: Cursor --- micro_sam/util.py | 1 - 1 file changed, 1 deletion(-) diff --git a/micro_sam/util.py b/micro_sam/util.py index 81bb14593..46ceb89e2 100644 --- a/micro_sam/util.py +++ b/micro_sam/util.py @@ -8,7 +8,6 @@ import hashlib import warnings from concurrent import futures -from concurrent import futures from pathlib import Path from collections import OrderedDict from typing import Any, Dict, Iterable, List, Optional, Tuple, Union, Callable From d781526d39d8c8d6d411aa282e479ae8191098e7 Mon Sep 17 00:00:00 2001 From: keejkrej Date: Wed, 20 May 2026 17:41:04 +0200 Subject: [PATCH 3/5] Add pip packaging metadata and defer conda-only imports Move project metadata from setup.cfg into pyproject.toml with pip-installable core deps and optional extras, while lazy-importing nifty, vigra, and python-elf only where needed so headless imports avoid conda-forge packages. Co-authored-by: Cursor --- micro_sam/util.py | 13 ++++--- pyproject.toml | 97 ++++++++++++++++++++++++++++++++++++++++++++++- setup.cfg | 60 ----------------------------- 3 files changed, 103 insertions(+), 67 deletions(-) delete mode 100644 setup.cfg diff --git a/micro_sam/util.py b/micro_sam/util.py index 46ceb89e2..8173d3d58 100644 --- a/micro_sam/util.py +++ b/micro_sam/util.py @@ -12,15 +12,17 @@ from collections import OrderedDict from typing import Any, Dict, Iterable, List, Optional, Tuple, Union, Callable -import zarr -import torch -import pooch -import xxhash -import numpy as np import imageio.v3 as imageio +import numpy as np +import pooch import segment_anything.utils.amg as amg_utils +import torch +import xxhash +import zarr + from skimage.measure import regionprops from skimage.segmentation import relabel_sequential +from torchvision.ops.boxes import batched_nms from .__version__ import __version__ from . import models as custom_models @@ -1888,7 +1890,6 @@ def apply_nms( scores = data["iou_preds"] * data["stability_scores"] boxes = _xywh_to_xyxy(data["global_boxes"] if is_tiled else data["boxes"]) if perform_box_nms: - from torchvision.ops.boxes import batched_nms assert not intersection_over_min # not implemented keep_by_nms = batched_nms( boxes, diff --git a/pyproject.toml b/pyproject.toml index 38c4ba011..df89c1e9e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,102 @@ [build-system] -requires = ["setuptools>=42.0.0", "wheel"] +requires = ["setuptools>=61", "wheel"] build-backend = "setuptools.build_meta" +[project] +name = "micro-sam" +description = "Segment Anything For Microscopy" +readme = "README.md" +license = "MIT" +license-files = ["LICENSE"] +requires-python = ">=3.10" +authors = [ + {name = "Anwai Archit"}, + {name = "Paul Hilt"}, + {name = "Genevieve Buckley"}, + {name = "Constantin Pape"}, +] +classifiers = [ + "Development Status :: 2 - Pre-Alpha", + "Framework :: napari", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Scientific/Engineering :: Image Processing", +] +dynamic = ["version"] +dependencies = [ + "imageio", + "numpy", + "pooch", + "scikit-image", + "scipy", + "segment-anything", + "torch>=2.5", + "torchvision", + "tqdm", + "xxhash", + "zarr", +] + +[project.optional-dependencies] +gui = [ + "h5py", + "magicgui", + "napari<0.7", + "natsort", + "PyQt5", +] +training = [ + "timm", + "torch-em>=0.8", +] +tracking = [ + "trackastra>=0.5.3", +] +bioimageio = [ + "bioimageio.core", + "bioimageio.spec", + "matplotlib", + "xarray", +] +mobile = [ + "mobile-sam @ git+https://github.com/ChaoningZhang/MobileSAM.git", +] + +[project.urls] +Homepage = "https://github.com/computational-cell-analytics/micro-sam" +Documentation = "https://computational-cell-analytics.github.io/micro-sam/micro_sam.html" +Repository = "https://github.com/computational-cell-analytics/micro-sam" +Issues = "https://github.com/computational-cell-analytics/micro-sam/issues" + +[project.scripts] +"micro_sam.annotator_2d" = "micro_sam.sam_annotator.annotator_2d:main" +"micro_sam.annotator_3d" = "micro_sam.sam_annotator.annotator_3d:main" +"micro_sam.annotator_tracking" = "micro_sam.sam_annotator.annotator_tracking:main" +"micro_sam.image_series_annotator" = "micro_sam.sam_annotator.image_series_annotator:main" +"micro_sam.precompute_embeddings" = "micro_sam.precompute_state:main" +"micro_sam.automatic_segmentation" = "micro_sam.automatic_segmentation:main" +"micro_sam.train" = "micro_sam.training.training:main" +"micro_sam.evaluate" = "micro_sam.evaluation.evaluation:main" +"micro_sam.info" = "micro_sam.util:micro_sam_info" +"micro_sam.benchmark_sam" = "micro_sam.evaluation.benchmark_datasets:main" + +[project.entry-points."napari.manifest"] +micro-sam = "micro_sam:napari.yaml" + +[tool.setuptools.dynamic] +version = {attr = "micro_sam.__version__"} + +[tool.setuptools.packages.find] +where = ["."] + +[tool.setuptools.package-data] +"*" = ["*.yaml"] + [tool.pytest.ini_options] addopts = "-v --durations=10 --cov=micro_sam --cov-report xml:coverage.xml --cov-report term-missing" markers = [ diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 24bbfec82..000000000 --- a/setup.cfg +++ /dev/null @@ -1,60 +0,0 @@ -[metadata] -name = micro-sam -version = attr: micro_sam.__version__ -description = Segment Anything For Microscopy -long_description = file: README.md -long_description_content_type = text/markdown -url = https://github.com/computational-cell-analytics/micro-sam -author = Anwai Archit, Paul Hilt, Genevieve Buckley, Constantin Pape -author_email = yourname@example.com -license = MIT -license_files = LICENSE -classifiers = - Development Status :: 2 - Pre-Alpha - Framework :: napari - Intended Audience :: Developers - License :: OSI Approved :: BSD License - Operating System :: OS Independent - Programming Language :: Python - Programming Language :: Python :: 3 - Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Topic :: Scientific/Engineering :: Image Processing -project_urls = - Bug Tracker = https://github.com/computational-cell-analytics/micro-sam/issues - Documentation = https://computational-cell-analytics.github.io/micro-sam/micro_sam.html - Source Code = https://github.com/computational-cell-analytics/micro-sam - User Support = https://github.com/computational-cell-analytics/micro-sam/issues - -[options] -packages = find: -python_requires = >=3.10 -include_package_data = True -package_dir = - = . - -[options.packages.find] -where = . - -# tell napari where to find to your manifest -[options.entry_points] -napari.manifest = - micro-sam = micro_sam:napari.yaml -console_scripts = - micro_sam.annotator_2d = micro_sam.sam_annotator.annotator_2d:main - micro_sam.annotator_3d = micro_sam.sam_annotator.annotator_3d:main - micro_sam.annotator_tracking = micro_sam.sam_annotator.annotator_tracking:main - micro_sam.image_series_annotator = micro_sam.sam_annotator.image_series_annotator:main - micro_sam.precompute_embeddings = micro_sam.precompute_state:main - micro_sam.automatic_segmentation = micro_sam.automatic_segmentation:main - micro_sam.train = micro_sam.training.training:main - micro_sam.evaluate = micro_sam.evaluation.evaluation:main - micro_sam.info = micro_sam.util:micro_sam_info - micro_sam.benchmark_sam = micro_sam.evaluation.benchmark_datasets:main - - -# make sure it gets included in your package -[options.package_data] -* = *.yaml From bf998534adfa321cefe12dbaa4a117dac33a8c1c Mon Sep 17 00:00:00 2001 From: keejkrej Date: Wed, 20 May 2026 17:41:45 +0200 Subject: [PATCH 4/5] Restore setup.cfg alongside pyproject.toml packaging metadata Co-authored-by: Cursor --- setup.cfg | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 setup.cfg diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 000000000..24bbfec82 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,60 @@ +[metadata] +name = micro-sam +version = attr: micro_sam.__version__ +description = Segment Anything For Microscopy +long_description = file: README.md +long_description_content_type = text/markdown +url = https://github.com/computational-cell-analytics/micro-sam +author = Anwai Archit, Paul Hilt, Genevieve Buckley, Constantin Pape +author_email = yourname@example.com +license = MIT +license_files = LICENSE +classifiers = + Development Status :: 2 - Pre-Alpha + Framework :: napari + Intended Audience :: Developers + License :: OSI Approved :: BSD License + Operating System :: OS Independent + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3 :: Only + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Topic :: Scientific/Engineering :: Image Processing +project_urls = + Bug Tracker = https://github.com/computational-cell-analytics/micro-sam/issues + Documentation = https://computational-cell-analytics.github.io/micro-sam/micro_sam.html + Source Code = https://github.com/computational-cell-analytics/micro-sam + User Support = https://github.com/computational-cell-analytics/micro-sam/issues + +[options] +packages = find: +python_requires = >=3.10 +include_package_data = True +package_dir = + = . + +[options.packages.find] +where = . + +# tell napari where to find to your manifest +[options.entry_points] +napari.manifest = + micro-sam = micro_sam:napari.yaml +console_scripts = + micro_sam.annotator_2d = micro_sam.sam_annotator.annotator_2d:main + micro_sam.annotator_3d = micro_sam.sam_annotator.annotator_3d:main + micro_sam.annotator_tracking = micro_sam.sam_annotator.annotator_tracking:main + micro_sam.image_series_annotator = micro_sam.sam_annotator.image_series_annotator:main + micro_sam.precompute_embeddings = micro_sam.precompute_state:main + micro_sam.automatic_segmentation = micro_sam.automatic_segmentation:main + micro_sam.train = micro_sam.training.training:main + micro_sam.evaluate = micro_sam.evaluation.evaluation:main + micro_sam.info = micro_sam.util:micro_sam_info + micro_sam.benchmark_sam = micro_sam.evaluation.benchmark_datasets:main + + +# make sure it gets included in your package +[options.package_data] +* = *.yaml From e267583bac849b099812be1d9a09a2d4c3135e25 Mon Sep 17 00:00:00 2001 From: keejkrej Date: Wed, 20 May 2026 17:48:50 +0200 Subject: [PATCH 5/5] Move pip dependencies to setup.cfg and revert pyproject.toml Keep packaging changes minimal for Cell-ACDC integration by declaring pip-only install_requires in setup.cfg instead of duplicating metadata in pyproject.toml. Co-authored-by: Cursor --- pyproject.toml | 97 +------------------------------------------------- setup.cfg | 12 +++++++ 2 files changed, 13 insertions(+), 96 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index df89c1e9e..38c4ba011 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,102 +1,7 @@ [build-system] -requires = ["setuptools>=61", "wheel"] +requires = ["setuptools>=42.0.0", "wheel"] build-backend = "setuptools.build_meta" -[project] -name = "micro-sam" -description = "Segment Anything For Microscopy" -readme = "README.md" -license = "MIT" -license-files = ["LICENSE"] -requires-python = ">=3.10" -authors = [ - {name = "Anwai Archit"}, - {name = "Paul Hilt"}, - {name = "Genevieve Buckley"}, - {name = "Constantin Pape"}, -] -classifiers = [ - "Development Status :: 2 - Pre-Alpha", - "Framework :: napari", - "Intended Audience :: Developers", - "Operating System :: OS Independent", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Topic :: Scientific/Engineering :: Image Processing", -] -dynamic = ["version"] -dependencies = [ - "imageio", - "numpy", - "pooch", - "scikit-image", - "scipy", - "segment-anything", - "torch>=2.5", - "torchvision", - "tqdm", - "xxhash", - "zarr", -] - -[project.optional-dependencies] -gui = [ - "h5py", - "magicgui", - "napari<0.7", - "natsort", - "PyQt5", -] -training = [ - "timm", - "torch-em>=0.8", -] -tracking = [ - "trackastra>=0.5.3", -] -bioimageio = [ - "bioimageio.core", - "bioimageio.spec", - "matplotlib", - "xarray", -] -mobile = [ - "mobile-sam @ git+https://github.com/ChaoningZhang/MobileSAM.git", -] - -[project.urls] -Homepage = "https://github.com/computational-cell-analytics/micro-sam" -Documentation = "https://computational-cell-analytics.github.io/micro-sam/micro_sam.html" -Repository = "https://github.com/computational-cell-analytics/micro-sam" -Issues = "https://github.com/computational-cell-analytics/micro-sam/issues" - -[project.scripts] -"micro_sam.annotator_2d" = "micro_sam.sam_annotator.annotator_2d:main" -"micro_sam.annotator_3d" = "micro_sam.sam_annotator.annotator_3d:main" -"micro_sam.annotator_tracking" = "micro_sam.sam_annotator.annotator_tracking:main" -"micro_sam.image_series_annotator" = "micro_sam.sam_annotator.image_series_annotator:main" -"micro_sam.precompute_embeddings" = "micro_sam.precompute_state:main" -"micro_sam.automatic_segmentation" = "micro_sam.automatic_segmentation:main" -"micro_sam.train" = "micro_sam.training.training:main" -"micro_sam.evaluate" = "micro_sam.evaluation.evaluation:main" -"micro_sam.info" = "micro_sam.util:micro_sam_info" -"micro_sam.benchmark_sam" = "micro_sam.evaluation.benchmark_datasets:main" - -[project.entry-points."napari.manifest"] -micro-sam = "micro_sam:napari.yaml" - -[tool.setuptools.dynamic] -version = {attr = "micro_sam.__version__"} - -[tool.setuptools.packages.find] -where = ["."] - -[tool.setuptools.package-data] -"*" = ["*.yaml"] - [tool.pytest.ini_options] addopts = "-v --durations=10 --cov=micro_sam --cov-report xml:coverage.xml --cov-report term-missing" markers = [ diff --git a/setup.cfg b/setup.cfg index 24bbfec82..64614b6e7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,6 +31,18 @@ project_urls = [options] packages = find: python_requires = >=3.10 +install_requires = + imageio + numpy + pooch + scikit-image + scipy + segment-anything + torch>=2.5 + torchvision + tqdm + xxhash + zarr include_package_data = True package_dir = = .