Skip to content

Commit

Permalink
Merge pull request #650 from fractal-analytics-platform/649-cellpose-…
Browse files Browse the repository at this point in the history
…options

Expand cellpose options
  • Loading branch information
jluethi authored Feb 15, 2024
2 parents e664082 + e7c1d74 commit cb37b44
Show file tree
Hide file tree
Showing 9 changed files with 747 additions and 7 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
**Note**: Numbers like (\#123) point to closed Pull Requests on the fractal-tasks-core repository.

# 0.14.2
* Add custom normalization options to the Cellpose task (#650)
* Add more options to the Cellpose task to control model behavior (#650)
* For Cellpose task, switch to using Enums for model_type (see issue #401)

# 0.14.1

* Fix bug in `cellpose_segmentation` upon using masked loading and setting `channel2` (\#639). Thanks [@FranziskaMoos-FMI](https://github.com/FranziskaMoos-FMI) and [@enricotagliavini](https://github.com/enricotagliavini).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

DOI="10.5281/zenodo.7059515"
CLEAN_DOI=${DOI/\//_}
zenodo_get $DOI -o ../images/${CLEAN_DOI}
139 changes: 139 additions & 0 deletions examples/06_cellpose_dev_example/run_example_cellpose_normalization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
"""
Copyright 2022 (C) Friedrich Miescher Institute for Biomedical Research and
University of Zurich
Original authors:
Marco Franzon <marco.franzon@exact-lab.it>
Tommaso Comparin <tommaso.comparin@exact-lab.it>
This file is part of Fractal and was originally developed by eXact lab S.r.l.
<exact-lab.it> under contract with Liberali Lab from the Friedrich Miescher
Institute for Biomedical Research and Pelkmans Lab from the University of
Zurich.
"""
import os

from devtools import debug

from fractal_tasks_core.channels import OmeroChannel
from fractal_tasks_core.channels import Window
from fractal_tasks_core.tasks.cellpose_segmentation import (
cellpose_segmentation,
)
from fractal_tasks_core.tasks.cellpose_transforms import (
CellposeCustomNormalizer,
)
from fractal_tasks_core.tasks.copy_ome_zarr import copy_ome_zarr
from fractal_tasks_core.tasks.create_ome_zarr import create_ome_zarr
from fractal_tasks_core.tasks.maximum_intensity_projection import (
maximum_intensity_projection,
)
from fractal_tasks_core.tasks.yokogawa_to_ome_zarr import yokogawa_to_ome_zarr

allowed_channels = [
OmeroChannel(
label="DAPI",
wavelength_id="A01_C01",
color="00FFFF",
window=Window(start=110, end=700),
)
]


num_levels = 6
coarsening_xy = 2


# Init
img_path = "../images/10.5281_zenodo.7059515/"
if not os.path.isdir(img_path):
raise FileNotFoundError(
f"{img_path} is missing,"
" try running ./fetch_test_data_from_zenodo.sh"
)
zarr_path = "tmp_out_normalize/"
metadata: dict = {}

# Create zarr structure
metadata_update = create_ome_zarr(
input_paths=[img_path],
output_path=zarr_path,
metadata=metadata,
image_extension="png",
allowed_channels=allowed_channels,
num_levels=num_levels,
coarsening_xy=coarsening_xy,
overwrite=True,
)
metadata.update(metadata_update)
debug(metadata)

# Yokogawa to zarr
for component in metadata["image"]:
yokogawa_to_ome_zarr(
input_paths=[zarr_path],
output_path=zarr_path,
metadata=metadata,
component=component,
)
debug(metadata)


# Copy zarr structure
metadata_update = copy_ome_zarr(
input_paths=[zarr_path],
output_path=zarr_path,
metadata=metadata,
suffix="mip",
overwrite=True,
)
metadata.update(metadata_update)

# Make MIP
for component in metadata["image"]:
metadata_update = maximum_intensity_projection(
input_paths=[zarr_path],
output_path=zarr_path,
metadata=metadata,
component=component,
)
metadata.update(metadata_update)


normalize = CellposeCustomNormalizer(default_normalize=True)
normalize = CellposeCustomNormalizer(
default_normalize=False, lower_percentile=1.0, upper_percentile=99.0
)
# normalize=CellposeCustomNormalizer(
# default_normalize=True,
# lower_percentile=1.0,
# upper_percentile=99.0
# ) # ValueError
# normalize=CellposeCustomNormalizer(
# default_normalize=False,
# lower_percentile=1.0,
# upper_percentile=99.0,
# lower_bound=100,
# upper_bound=500
# ) # ValueError
normalize = CellposeCustomNormalizer(
default_normalize=False, lower_bound=100, upper_bound=500
)


# Per-FOV labeling
for component in metadata["image"]:
cellpose_segmentation(
input_paths=[zarr_path],
output_path=zarr_path,
metadata=metadata,
component=component,
channel=dict(wavelength_id="A01_C01"),
level=1,
relabeling=True,
diameter_level0=40.0,
model_type="cyto2",
normalize=normalize,
)
metadata.update(metadata_update)
debug(metadata)
117 changes: 117 additions & 0 deletions fractal_tasks_core/__FRACTAL_MANIFEST__.json
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,23 @@
"model_type": {
"title": "Model Type",
"default": "cyto2",
"enum": [
"cyto",
"nuclei",
"tissuenet",
"livecell",
"cyto2",
"general",
"CP",
"CPx",
"TN1",
"TN2",
"TN3",
"LC1",
"LC2",
"LC3",
"LC4"
],
"type": "string",
"description": "Parameter of `CellposeModel` class. Defines which model should be used. Typical choices are `nuclei`, `cyto`, `cyto2`, etc."
},
Expand All @@ -459,6 +476,22 @@
"type": "number",
"description": "Parameter of `CellposeModel.eval` method. Valid values between 0.0 and 1.0. From Cellpose documentation: \"Increase this threshold if cellpose is not returning as many ROIs as you\u2019d expect. Similarly, decrease this threshold if cellpose is returning too many ill-shaped ROIs.\""
},
"normalize": {
"title": "Normalize",
"default": {
"type": "default",
"lower_percentile": null,
"upper_percentile": null,
"lower_bound": null,
"upper_bound": null
},
"allOf": [
{
"$ref": "#/definitions/CellposeCustomNormalizer"
}
],
"description": "By default, data is normalized so 0.0=1st percentile and 1.0=99th percentile of image intensities in each channel. This automatic normalization can lead to issues when the image to be segmented is very sparse. You can turn off the default rescaling. With the \"custom\" option, you can either provide your own rescaling percentiles or fixed rescaling upper and lower bound integers."
},
"anisotropy": {
"title": "Anisotropy",
"type": "number",
Expand Down Expand Up @@ -488,6 +521,48 @@
"type": "boolean",
"description": "If `False`, always use the CPU; if `True`, use the GPU if possible (as defined in `cellpose.core.use_gpu()`) and fall-back to the CPU otherwise."
},
"batch_size": {
"title": "Batch Size",
"default": 8,
"type": "integer",
"description": "number of 224x224 patches to run simultaneously on the GPU (can make smaller or bigger depending on GPU memory usage)"
},
"invert": {
"title": "Invert",
"default": false,
"type": "boolean",
"description": "invert image pixel intensity before running network (if True, image is also normalized)"
},
"tile": {
"title": "Tile",
"default": true,
"type": "boolean",
"description": "tiles image to ensure GPU/CPU memory usage limited (recommended)"
},
"tile_overlap": {
"title": "Tile Overlap",
"default": 0.1,
"type": "number",
"description": "fraction of overlap of tiles when computing flows"
},
"resample": {
"title": "Resample",
"default": true,
"type": "boolean",
"description": "run dynamics at original image size (will be slower but create more accurate boundaries)"
},
"interp": {
"title": "Interp",
"default": true,
"type": "boolean",
"description": "interpolate during 2D dynamics (not available in 3D) (in previous versions it was False, now it defaults to True)"
},
"stitch_threshold": {
"title": "Stitch Threshold",
"default": 0.0,
"type": "number",
"description": "if stitch_threshold>0.0 and not do_3D and equal image sizes, masks are stitched in 3D to return volume segmentation"
},
"overwrite": {
"title": "Overwrite",
"default": true,
Expand Down Expand Up @@ -521,6 +596,48 @@
"description": "Name of the channel."
}
}
},
"CellposeCustomNormalizer": {
"title": "CellposeCustomNormalizer",
"description": "Validator to handle different normalization scenarios for Cellpose models",
"type": "object",
"properties": {
"type": {
"title": "Type",
"default": "default",
"enum": [
"default",
"custom",
"no_normalization"
],
"type": "string",
"description": "One of `default` (Cellpose default normalization), `custom` (using the other custom parameters) or `no_normalization`."
},
"lower_percentile": {
"title": "Lower Percentile",
"minimum": 0,
"maximum": 100,
"type": "number",
"description": "Specify a custom lower-bound percentile for rescaling as a float value between 0 and 100. Set to 1 to run the same as default). You can only specify percentiles or bounds, not both."
},
"upper_percentile": {
"title": "Upper Percentile",
"minimum": 0,
"maximum": 100,
"type": "number",
"description": "Specify a custom upper-bound percentile for rescaling as a float value between 0 and 100. Set to 99 to run the same as default, set to e.g. 99.99 if the default rescaling was too harsh. You can only specify percentiles or bounds, not both."
},
"lower_bound": {
"title": "Lower Bound",
"type": "integer",
"description": "Explicit lower bound value to rescale the image at. Needs to be an integer, e.g. 100. You can only specify percentiles or bounds, not both."
},
"upper_bound": {
"title": "Upper Bound",
"type": "integer",
"description": "Explicit upper bound value to rescale the image at. Needs to be an integer, e.g. 2000. You can only specify percentiles or bounds, not both."
}
}
}
}
},
Expand Down
5 changes: 5 additions & 0 deletions fractal_tasks_core/dev/lib_args_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@
"tasks/napari_workflows_wrapper_models.py",
"NapariWorkflowsOutput",
),
(
"fractal_tasks_core",
"tasks/cellpose_transforms.py",
"CellposeCustomNormalizer",
),
]


Expand Down
Loading

0 comments on commit cb37b44

Please sign in to comment.