-
Notifications
You must be signed in to change notification settings - Fork 1
Implement SGN detection #69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
90087c4
Implement SGN detection
schilling40 caba462
Make segmentation thread-safe
schilling40 c4f2b91
Fixed data type for MoBIE
schilling40 20369b7
Update detection parameters
schilling40 41dbc51
Marker extension of SGN segmentation
schilling40 ad032c8
Addressed feedback
schilling40 01d1352
Include marker extension in SGN detection
schilling40 3501408
Add template for processing
schilling40 47f501c
Update environment.yaml
constantinpape File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| import multiprocessing as mp | ||
| from concurrent import futures | ||
| import os | ||
| from typing import Optional, Tuple | ||
|
|
||
| import numpy as np | ||
| import pandas as pd | ||
| import zarr | ||
|
|
||
| from elf.io import open_file | ||
| from elf.parallel.local_maxima import find_local_maxima | ||
| from flamingo_tools.segmentation.unet_prediction import prediction_impl | ||
| from tqdm import tqdm | ||
|
|
||
|
|
||
| def sgn_detection( | ||
| input_path: str, | ||
| input_key: str, | ||
| output_folder: str, | ||
| model_path: str, | ||
| block_shape: Optional[Tuple[int, int, int]] = None, | ||
| halo: Optional[Tuple[int, int, int]] = None, | ||
| spot_radius: int = 4, | ||
| ): | ||
| """Run prediction for sgn detection. | ||
|
|
||
| Args: | ||
| input_path: Input path to image channel for SGN detection. | ||
| input_key: Input key for resolution of image channel and mask channel. | ||
| output_folder: Output folder for SGN segmentation. | ||
| model_path: Path to model for SGN detection. | ||
| block_shape: The block-shape for running the prediction. | ||
| halo: The halo (= block overlap) to use for prediction. | ||
| spot_radius: Radius in pixel to convert spot detection of SGNs into a volume. | ||
| """ | ||
| if block_shape is None: | ||
| block_shape = (24, 256, 256) | ||
| if halo is None: | ||
| halo = (12, 64, 64) | ||
|
|
||
| # Skip existing prediction, which is saved in output_folder/predictions.zarr | ||
| skip_prediction = False | ||
| output_path = os.path.join(output_folder, "predictions.zarr") | ||
| prediction_key = "prediction" | ||
| if os.path.exists(output_path) and prediction_key in zarr.open(output_path, "r"): | ||
| skip_prediction = True | ||
|
|
||
| if not skip_prediction: | ||
| prediction_impl( | ||
| input_path, input_key, output_folder, model_path, | ||
| scale=None, block_shape=block_shape, halo=halo, | ||
| apply_postprocessing=False, output_channels=1, | ||
| ) | ||
|
|
||
| detection_path = os.path.join(output_folder, "SGN_detection.tsv") | ||
| detection_path = os.path.join(output_folder, "SGN_detection.tsv") | ||
| if not os.path.exists(detection_path): | ||
| input_ = zarr.open(output_path, "r")[prediction_key] | ||
| detections = find_local_maxima( | ||
| input_, block_shape=block_shape, min_distance=4, threshold_abs=0.5, verbose=True, n_threads=16, | ||
| ) | ||
|
|
||
| print(detections.shape) | ||
|
|
||
| shape = input_.shape | ||
| chunks = (128, 128, 128) | ||
| segmentation_path = os.path.join(output_folder, "segmentation.zarr") | ||
| output = open_file(segmentation_path, mode="a") | ||
| segmentation_key = "segmentation" | ||
| output_dataset = output.create_dataset( | ||
| segmentation_key, shape=shape, dtype=input_.dtype, | ||
| chunks=chunks, compression="gzip" | ||
| ) | ||
|
|
||
| def add_halo_segm(detection_index): | ||
| """Create a segmentation volume around all detected spots. | ||
| """ | ||
| coord = detections[detection_index] | ||
| block_begin = [round(c) - spot_radius for c in coord] | ||
| block_end = [round(c) + spot_radius for c in coord] | ||
| volume_index = tuple(slice(beg, end) for beg, end in zip(block_begin, block_end)) | ||
| output_dataset[volume_index] = detection_index + 1 | ||
|
|
||
| # Limit the number of cores for parallelization. | ||
| n_threads = min(16, mp.cpu_count()) | ||
| with futures.ThreadPoolExecutor(n_threads) as filter_pool: | ||
| list(tqdm(filter_pool.map(add_halo_segm, range(len(detections))), total=len(detections))) | ||
|
|
||
| # Save the result in mobie compatible format. | ||
| detections = np.concatenate( | ||
| [np.arange(1, len(detections) + 1)[:, None], detections[:, ::-1]], axis=1 | ||
| ) | ||
| detections = pd.DataFrame(detections, columns=["spot_id", "x", "y", "z"]) | ||
| detections.to_csv(detection_path, index=False, sep="\t") | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| import argparse | ||
|
|
||
| import flamingo_tools.s3_utils as s3_utils | ||
| from flamingo_tools.segmentation.sgn_detection import sgn_detection | ||
|
|
||
|
|
||
| def main(): | ||
|
|
||
| parser = argparse.ArgumentParser() | ||
| parser.add_argument("-i", "--input", required=True, help="Path to image data to be segmented.") | ||
| parser.add_argument("-o", "--output_folder", required=True, help="Path to output folder.") | ||
| parser.add_argument("-m", "--model", required=True, | ||
| help="Path to SGN detection model.") | ||
| parser.add_argument("-k", "--input_key", default=None, | ||
| help="The key / internal path to image data.") | ||
|
|
||
| parser.add_argument("--s3", action="store_true", help="Use S3 bucket.") | ||
| parser.add_argument("--s3_credentials", type=str, default=None, | ||
| help="Input file containing S3 credentials. " | ||
| "Optional if AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY were exported.") | ||
| parser.add_argument("--s3_bucket_name", type=str, default=None, | ||
| help="S3 bucket name. Optional if BUCKET_NAME was exported.") | ||
| parser.add_argument("--s3_service_endpoint", type=str, default=None, | ||
| help="S3 service endpoint. Optional if SERVICE_ENDPOINT was exported.") | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
| block_shape = (24, 256, 256) | ||
| halo = (12, 64, 64) | ||
|
|
||
| if args.s3: | ||
| input_path, fs = s3_utils.get_s3_path(args.input, bucket_name=args.s3_bucket_name, | ||
| service_endpoint=args.s3_service_endpoint, | ||
| credential_file=args.s3_credentials) | ||
|
|
||
| else: | ||
| input_path = args.input | ||
|
|
||
| sgn_detection(input_path=input_path, input_key=args.input_key, output_folder=args.output_folder, | ||
| model_path=args.model, block_shape=block_shape, halo=halo) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.