From 12e1ede1c7ad9fb1a99f2288cf78b1da1b00ba07 Mon Sep 17 00:00:00 2001 From: Philipp Otto Date: Fri, 17 May 2019 16:15:35 +0200 Subject: [PATCH] Add anisotropic parameter to downsampling tool (#88) * add anisotropic parameter to downsampling tool * black * incorporate feedback --- README.md | 2 +- wkcuber/downsampling.py | 48 ++++++++++++++++++++++++++++++++++++----- wkcuber/utils.py | 4 ++-- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 6a14169f0..73d5f24b0 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Created with [Python3](https://www.python.org/). * `wkcuber.cubing`: Convert image stacks (e.g., `tiff`, `jpg`, `png`, `dm3`) to WKW cubes * `wkcuber.tile_cubing`: Convert tiled image stacks (e.g. in `z/y/x.ext` folder structure) to WKW cubes * `wkcuber.convert_knossos`: Convert KNOSSOS cubes to WKW cubes -* `wkcuber.downsampling`: Create downsampled magnifications (with `median`, `mode` and linear interpolation modes) +* `wkcuber.downsampling`: Create downsampled magnifications (with `median`, `mode` and linear interpolation modes). Downsampling compresses the new magnifications by default (disable via `--no-compress`). * `wkcuber.compress`: Compress WKW cubes for efficient file storage (especially useful for segmentation data) * `wkcuber.metadata`: Create (or refresh) metadata (with guessing of most parameters) * Most modules support multiprocessing diff --git a/wkcuber/downsampling.py b/wkcuber/downsampling.py index 1f4d66acd..2e88779ff 100644 --- a/wkcuber/downsampling.py +++ b/wkcuber/downsampling.py @@ -10,6 +10,7 @@ from functools import lru_cache from enum import Enum from .mag import Mag +from wkcuber.metadata import read_datasource_properties from .utils import ( add_verbose_flag, @@ -21,6 +22,7 @@ add_distribution_flags, get_executor_for_args, wait_and_ensure_success, + add_anisotropic_flag, ) DEFAULT_EDGE_LEN = 256 @@ -73,11 +75,21 @@ def create_parser(): # Either provide the maximum resolution to be downsampled OR a specific, anisotropic magnification. group = parser.add_mutually_exclusive_group() group.add_argument( - "--max", "-m", help="Max resolution to be downsampled", type=int, default=512 + "--max", + "-m", + help="Max resolution to be downsampled. In case of anisotropic downsampling, the process is considered " + "done when max(current_mag) >= max(max_mag) where max takes the largest dimension of the mag tuple " + "x, y, z. For example, a maximum mag value of 8 (or 8-8-8) will stop the downsampling as soon as a " + "magnification is produced for which one dimension is equal or larger than 8.", + type=int, + default=512, ) group.add_argument( "--anisotropic_target_mag", - help="Specify an anisotropic target magnification which should be created (e.g., --anisotropic_target_mag 2-2-1)", + help="Specify an explicit anisotropic target magnification which should be " + "created (e.g., --anisotropic_target_mag 2-2-1). Consider using --anisotropic " + "instead which automatically creates multiple anisotropic magnifications depending " + "on the dataset's scale", type=str, ) @@ -90,10 +102,14 @@ def create_parser(): ) parser.add_argument( - "--compress", action="store_true", help="Compress data during downsampling" + "--no_compress", + help="Don't compress data during downsampling", + default=False, + action="store_true", ) add_verbose_flag(parser) + add_anisotropic_flag(parser) add_distribution_flags(parser) return parser @@ -530,7 +546,29 @@ def detect_larger_and_smaller_dimension(scale): anisotropic_target_mag, args.interpolation_mode, args.buffer_cube_size, - args.compress, + not args.no_compress, + args, + ) + elif args.anisotropic: + try: + scale = read_datasource_properties(args.path)["scale"] + except Exception as exc: + logging.error( + "Could not determine scale which is necessary " + "to find target magnifications for anisotropic downsampling. " + "Does the provided dataset have a datasource-properties.json file?" + ) + raise exc + + downsample_mags_anisotropic( + args.path, + args.layer_name, + from_mag, + max_mag, + scale, + args.interpolation_mode, + DEFAULT_EDGE_LEN, + not args.no_compress, args, ) else: @@ -541,6 +579,6 @@ def detect_larger_and_smaller_dimension(scale): max_mag, args.interpolation_mode, args.buffer_cube_size, - args.compress, + not args.no_compress, args, ) diff --git a/wkcuber/utils.py b/wkcuber/utils.py index 33a28742a..a8c031ec6 100644 --- a/wkcuber/utils.py +++ b/wkcuber/utils.py @@ -65,8 +65,8 @@ def add_anisotropic_flag(parser): parser.add_argument( "--anisotropic", "-a", - help="Activates Anisotropic downsampling. It will detect which dimension ist the smallest and the largest. " - "The largest dimension will only be down sampled by 2 if it would be smaller or equal to the smallest " + help="Activates Anisotropic downsampling. It will detect which dimension is the smallest and the largest. " + "The largest dimension will only be downsampled by 2 if it would be smaller or equal to the smallest " "dimension in the next downsampling step.", dest="anisotropic", action="store_true",