Skip to content

Commit

Permalink
Merge pull request #165 from GenevieveBuckley/napari-plugin
Browse files Browse the repository at this point in the history
micro-sam napari plugin
  • Loading branch information
constantinpape authored Aug 31, 2023
2 parents 4e4df74 + e3e5d10 commit 43cf2c5
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 27 deletions.
5 changes: 5 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include LICENSE
include README.md

recursive-exclude * __pycache__
recursive-exclude * *.py[co]
47 changes: 47 additions & 0 deletions micro_sam/napari.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: micro-sam
display_name: SegmentAnything for Microscopy
contributions:
commands:
- id: micro-sam.sample_data_image_series
python_name: micro_sam.sample_data:sample_data_image_series
title: Load image series sample data from micro-sam plugin
- id: micro-sam.sample_data_wholeslide
python_name: micro_sam.sample_data:sample_data_wholeslide
title: Load WholeSlide sample data from micro-sam plugin
- id: micro-sam.sample_data_livecell
python_name: micro_sam.sample_data:sample_data_livecell
title: Load LiveCell sample data from micro-sam plugin
- id: micro-sam.sample_data_hela_2d
python_name: micro_sam.sample_data:sample_data_hela_2d
title: Load 2D Hela sample data from micro-sam plugin
- id: micro-sam.sample_data_3d
python_name: micro_sam.sample_data:sample_data_3d
title: Load Lucchi++ 3D sample data from micro-sam plugin
- id: micro-sam.sample_data_tracking
python_name: micro_sam.sample_data:sample_data_tracking
title: Load tracking sample data from micro-sam plugin
- id: micro-sam.sample_data_segmentation
python_name: micro_sam.sample_data:sample_data_segmentation
title: Load segmentation sample data from micro-sam plugin
sample_data:
- command: micro-sam.sample_data_image_series
display_name: Image series example data
key: micro-sam-image-series
- command: micro-sam.sample_data_wholeslide
display_name: WholeSlide example data
key: micro-sam-wholeslide
- command: micro-sam.sample_data_livecell
display_name: LiveCell example data
key: micro-sam-livecell
- command: micro-sam.sample_data_hela_2d
display_name: HeLa 2d example data
key: micro-sam-hela2d
- command: micro-sam.sample_data_3d
display_name: Lucchi++ 3d dataset
key: micro-sam-lucchi
- command: micro-sam.sample_data_tracking
display_name: Tracking sample dataset
key: micro-sam-tracking
- command: micro-sam.sample_data_segmentation
display_name: Segmentation sample dataset
key: micro-sam-segmentation
122 changes: 119 additions & 3 deletions micro_sam/sample_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from pathlib import Path
from typing import Union

import imageio.v3 as imageio
import numpy as np
import pooch


Expand All @@ -17,6 +19,9 @@ def fetch_image_series_example_data(save_directory: Union[str, os.PathLike]) ->
Returns:
The folder that contains the downloaded data.
"""
# This sample dataset is currently not provided to napari by the micro-sam
# plugin, because images are not all the same shape and cannot be combined
# into a single layer
save_directory = Path(save_directory)
os.makedirs(save_directory, exist_ok=True)
print("Example data directory is:", save_directory.resolve())
Expand All @@ -36,6 +41,26 @@ def fetch_image_series_example_data(save_directory: Union[str, os.PathLike]) ->
return data_folder


def sample_data_image_series():
"""Provides image series example image to napari.
Opens as three separate image layers in napari (one per image in series).
The third image in the series has a different size and modality.
"""
# Return list of tuples
# [(data1, add_image_kwargs1), (data2, add_image_kwargs2)]
# Check the documentation for more information about the
# add_image_kwargs
# https://napari.org/stable/api/napari.Viewer.html#napari.Viewer.add_image
default_base_data_dir = pooch.os_cache('micro-sam')
data_directory = fetch_image_series_example_data(default_base_data_dir)
fnames = os.listdir(data_directory)
full_filenames = [os.path.join(data_directory, f) for f in fnames]
full_filenames.sort()
data_and_image_kwargs = [(imageio.imread(f), {"name": f"img-{i}"}) for i, f in enumerate(full_filenames)]
return data_and_image_kwargs


def fetch_wholeslide_example_data(save_directory: Union[str, os.PathLike]) -> str:
"""Download the sample data for the 2d annotator.
Expand All @@ -61,6 +86,20 @@ def fetch_wholeslide_example_data(save_directory: Union[str, os.PathLike]) -> st
return os.path.join(save_directory, fname)


def sample_data_wholeslide():
"""Provides wholeslide 2d example image to napari."""
# Return list of tuples
# [(data1, add_image_kwargs1), (data2, add_image_kwargs2)]
# Check the documentation for more information about the
# add_image_kwargs
# https://napari.org/stable/api/napari.Viewer.html#napari.Viewer.add_image
default_base_data_dir = pooch.os_cache('micro-sam')
filename = fetch_wholeslide_example_data(default_base_data_dir)
data = imageio.imread(filename)
add_image_kwargs = {"name": "wholeslide"}
return [(data, add_image_kwargs)]


def fetch_livecell_example_data(save_directory: Union[str, os.PathLike]) -> str:
"""Download the sample data for the 2d annotator.
Expand All @@ -74,7 +113,6 @@ def fetch_livecell_example_data(save_directory: Union[str, os.PathLike]) -> str:
"""
save_directory = Path(save_directory)
os.makedirs(save_directory, exist_ok=True)
print("Example data directory is:", save_directory.resolve())
fname = "livecell-2d-image.png"
pooch.retrieve(
url="https://owncloud.gwdg.de/index.php/s/fSaOJIOYjmFBjPM/download",
Expand All @@ -86,7 +124,21 @@ def fetch_livecell_example_data(save_directory: Union[str, os.PathLike]) -> str:
return os.path.join(save_directory, fname)


def fetch_hela_2d_example_data(save_directory: Union[str, os.PathLike]) -> str:
def sample_data_livecell():
"""Provides livecell 2d example image to napari."""
# Return list of tuples
# [(data1, add_image_kwargs1), (data2, add_image_kwargs2)]
# Check the documentation for more information about the
# add_image_kwargs
# https://napari.org/stable/api/napari.Viewer.html#napari.Viewer.add_image
default_base_data_dir = pooch.os_cache('micro-sam')
filename = fetch_livecell_example_data(default_base_data_dir)
data = imageio.imread(filename)
add_image_kwargs = {"name": "livecell"}
return [(data, add_image_kwargs)]


def fetch_hela_2d_example_data(save_directory: Union[str, os.PathLike]) -> Union[str, os.PathLike]:
"""Download the sample data for the 2d annotator.
This downloads a single image from the HeLa CTC dataset.
Expand All @@ -110,6 +162,20 @@ def fetch_hela_2d_example_data(save_directory: Union[str, os.PathLike]) -> str:
return os.path.join(save_directory, fname)


def sample_data_hela_2d():
"""Provides HeLa 2d example image to napari."""
# Return list of tuples
# [(data1, add_image_kwargs1), (data2, add_image_kwargs2)]
# Check the documentation for more information about the
# add_image_kwargs
# https://napari.org/stable/api/napari.Viewer.html#napari.Viewer.add_image
default_base_data_dir = pooch.os_cache("micro-sam")
filename = fetch_hela_2d_example_data(default_base_data_dir)
data = imageio.imread(filename)
add_image_kwargs = {"name": "hela_2d"}
return [(data, add_image_kwargs)]


def fetch_3d_example_data(save_directory: Union[str, os.PathLike]) -> str:
"""Download the sample data for the 3d annotator.
Expand Down Expand Up @@ -139,6 +205,23 @@ def fetch_3d_example_data(save_directory: Union[str, os.PathLike]) -> str:
return str(lucchi_dir)


def sample_data_3d():
"""Provides Lucchi++ 3d example image to napari."""
# Return list of tuples
# [(data1, add_image_kwargs1), (data2, add_image_kwargs2)]
# Check the documentation for more information about the
# add_image_kwargs
# https://napari.org/stable/api/napari.Viewer.html#napari.Viewer.add_image
default_base_data_dir = pooch.os_cache("micro-sam")
data_directory = fetch_3d_example_data(default_base_data_dir)
fnames = os.listdir(data_directory)
full_filenames = [os.path.join(data_directory, f) for f in fnames]
full_filenames.sort()
data = np.stack([imageio.imread(f) for f in full_filenames], axis=0)
add_image_kwargs = {"name": "lucchi++"}
return [(data, add_image_kwargs)]


def fetch_tracking_example_data(save_directory: Union[str, os.PathLike]) -> str:
"""Download the sample data for the tracking annotator.
Expand All @@ -156,7 +239,6 @@ def fetch_tracking_example_data(save_directory: Union[str, os.PathLike]) -> str:
"""
save_directory = Path(save_directory)
os.makedirs(save_directory, exist_ok=True)
print("Example data directory is:", save_directory.resolve())
unpack_filenames = [os.path.join("DIC-C2DH-HeLa", "01", f"t{str(i).zfill(3)}.tif") for i in range(84)]
unpack = pooch.Unzip(members=unpack_filenames)
fname = "DIC-C2DH-HeLa.zip"
Expand All @@ -173,6 +255,23 @@ def fetch_tracking_example_data(save_directory: Union[str, os.PathLike]) -> str:
return str(cell_tracking_dir)


def sample_data_tracking():
"""Provides tracking example dataset to napari."""
# Return list of tuples
# [(data1, add_image_kwargs1), (data2, add_image_kwargs2)]
# Check the documentation for more information about the
# add_image_kwargs
# https://napari.org/stable/api/napari.Viewer.html#napari.Viewer.add_image
default_base_data_dir = pooch.os_cache("micro-sam")
data_directory = fetch_tracking_example_data(default_base_data_dir)
fnames = os.listdir(data_directory)
full_filenames = [os.path.join(data_directory, f) for f in fnames]
full_filenames.sort()
data = np.stack([imageio.imread(f) for f in full_filenames], axis=0)
add_image_kwargs = {"name": "tracking"}
return [(data, add_image_kwargs)]


def fetch_tracking_segmentation_data(save_directory: Union[str, os.PathLike]) -> str:
"""Download groundtruth segmentation for the tracking example data.
Expand Down Expand Up @@ -200,3 +299,20 @@ def fetch_tracking_segmentation_data(save_directory: Union[str, os.PathLike]) ->
cell_tracking_dir = save_directory.joinpath(f"{fname}.unzip", "masks")
assert os.path.exists(cell_tracking_dir)
return str(cell_tracking_dir)


def sample_data_segmentation():
"""Provides segmentation example dataset to napari."""
# Return list of tuples
# [(data1, add_image_kwargs1), (data2, add_image_kwargs2)]
# Check the documentation for more information about the
# add_image_kwargs
# https://napari.org/stable/api/napari.Viewer.html#napari.Viewer.add_image
default_base_data_dir = pooch.os_cache("micro-sam")
data_directory = fetch_tracking_segmentation_data(default_base_data_dir)
fnames = os.listdir(data_directory)
full_filenames = [os.path.join(data_directory, f) for f in fnames]
full_filenames.sort()
data = np.stack([imageio.imread(f) for f in full_filenames], axis=0)
add_image_kwargs = {"name": "segmentation"}
return [(data, add_image_kwargs)]
55 changes: 55 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[build-system]
requires = ["setuptools>=42.0.0", "wheel"]
build-backend = "setuptools.build_meta"


[tool.black]
line-length = 79
target-version = ['py38', 'py39', 'py310']


[tool.ruff]
line-length = 79
select = [
"E", "F", "W", #flake8
"UP", # pyupgrade
"I", # isort
"BLE", # flake8-blind-exception
"B", # flake8-bugbear
"A", # flake8-builtins
"C4", # flake8-comprehensions
"ISC", # flake8-implicit-str-concat
"G", # flake8-logging-format
"PIE", # flake8-pie
"SIM", # flake8-simplify
]
ignore = [
"E501", # line too long. let black handle this
"UP006", "UP007", # type annotation. As using magicgui require runtime type annotation then we disable this.
"SIM117", # flake8-simplify - some of merged with statements are not looking great with black, reanble after drop python 3.9
]

exclude = [
".bzr",
".direnv",
".eggs",
".git",
".mypy_cache",
".pants.d",
".ruff_cache",
".svn",
".tox",
".venv",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"venv",
"*vendored*",
"*_vendor*",
]

target-version = "py38"
fix = true
56 changes: 56 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
[metadata]
name = micro-sam
version = attr: micro_sam.__version__
description = SegmentAnything 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, Constantin Pape
author_email = [email protected]
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.8
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

# make sure it gets included in your package
[options.package_data]
* = *.yaml

[project.scripts]
micro_sam.annotator = "micro_sam.sam_annotator.annotator:main"
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.util:main"
24 changes: 0 additions & 24 deletions setup.py

This file was deleted.

0 comments on commit 43cf2c5

Please sign in to comment.