Source code for topostats.validation

"""Validation of configuration."""

import logging
import os
from pathlib import Path

from schema import And, Optional, Or, Schema, SchemaError

from topostats.logs.logs import LOGGER_NAME

LOGGER = logging.getLogger(LOGGER_NAME)

# pylint: disable=line-too-long
# pylint: disable=too-many-lines


[docs] def validate_config(config: dict, schema: Schema, config_type: str) -> None: """ Validate configuration. Parameters ---------- config : dict Config dictionary imported by read_yaml() and parsed through clean_config(). schema : Schema A schema against which the configuration is to be compared. config_type : str Description of of configuration being validated. """ try: schema.validate(config) LOGGER.info(f"The {config_type} is valid.") except SchemaError as schema_error: raise SchemaError( f"There is an error in your {config_type} configuration. " "Please refer to the first error message above for details" ) from schema_error
DEFAULT_CONFIG_SCHEMA = Schema( { "base_dir": Path, "output_dir": Path, "log_level": Or( "debug", "info", "warning", "error", error="Invalid value in config for 'log_level', valid values are 'info' (default), 'debug', 'error' or 'warning", ), "cores": lambda n: 1 <= n <= os.cpu_count(), "file_ext": Or( ".spm", ".asd", ".jpk", ".ibw", ".gwy", ".topostats", error="Invalid value in config for 'file_ext', valid values are '.spm', '.jpk', '.ibw', '.gwy', '.topostats', or '.asd'.", ), "loading": {"channel": str}, "filter": { "run": Or( True, False, error="Invalid value in config for 'filter.run', valid values are 'True' or 'False'", ), "row_alignment_quantile": lambda n: 0.0 <= n <= 1.0, "threshold_method": Or( "absolute", "otsu", "std_dev", error=( "Invalid value in config for 'filter.threshold_method', valid values " "are 'absolute', 'otsu' or 'std_dev'" ), ), "otsu_threshold_multiplier": float, "threshold_std_dev": { "below": lambda n: n > 0, "above": lambda n: n > 0, }, "threshold_absolute": { "below": Or( int, float, error=( "Invalid value in config for filter.threshold.absolute.below " "should be type int or float" ), ), "above": Or( int, float, error=( "Invalid value in config for filter.threshold.absolute.below " "should be type int or float" ), ), }, "gaussian_size": float, "gaussian_mode": Or( "nearest", error="Invalid value in config for 'filter.gaussian_mode', valid values are 'nearest'", ), "remove_scars": { "run": bool, "removal_iterations": lambda n: 0 <= n < 10, "threshold_low": lambda n: n > 0, "threshold_high": lambda n: n > 0, "max_scar_width": lambda n: n >= 1, "min_scar_length": lambda n: n >= 1, }, }, "grains": { "run": Or( True, False, error="Invalid value in config for grains.run, valid values are 'True' or 'False'", ), "smallest_grain_size_nm2": lambda n: n > 0.0, "threshold_method": Or( "absolute", "otsu", "std_dev", error=( "Invalid value in config for 'grains.threshold_method', valid values " "are 'absolute', 'otsu' or 'std_dev'" ), ), "otsu_threshold_multiplier": float, "threshold_std_dev": { "below": lambda n: n > 0, "above": lambda n: n > 0, }, "threshold_absolute": { "below": Or( int, float, error=( "Invalid value in config for grains.threshold.absolute.below " "should be type int or float" ), ), "above": Or( int, float, error=( "Invalid value in config for grains.threshold.absolute.below " "should be type int or float" ), ), }, "absolute_area_threshold": { "above": [ Or( int, None, error=( "Invalid value in config for 'grains.absolute_area_threshold.above', valid values " "are int or null" ), ) ], "below": [ Or( int, None, error=( "Invalid value in config for 'grains.absolute_area_threshold.below', valid values " "are int or null" ), ) ], }, "direction": Or( "both", "below", "above", error="Invalid direction for grains.direction valid values are 'both', 'below' or 'above", ), "remove_edge_intersecting_grains": Or( True, False, error="Invalid value in config for 'grains.remove_edge_intersecting_grains', valid values are 'True' or 'False'", ), "unet_config": { "model_path": Or(None, str), "grain_crop_padding": int, "upper_norm_bound": float, "lower_norm_bound": float, }, "vetting": { "class_conversion_size_thresholds": Or( None, # List of lists of 3 integers and 2 integers [[[int, int, int], [int, int]]], error="Invalid value in config for 'grainstats.vetting.class_conversion_size_thresholds', this " "needs to be a list of lists of 3 integers and 2 integers - [class number, class to convert to " "if too small, class to convert to if too big] and [minimum size, maximum size]", ), "class_region_number_thresholds": Or( None, # List of lists of 3 integers [[int, int, int]], error="Invalid value in config for 'grainstats.vetting.class_region_number_thresholds', this needs" "to be a list of lists of 3 integers - class number, minimum region number, maximum region number", ), "class_size_thresholds": Or( None, # List of lists of 3 integers [[int, int, int]], error="Invalid value in config for 'grainstats.vetting.class_size_thresholds', this needs to be a" "list of lists of 3 integers - class number, minimum size, maximum size", ), "nearby_conversion_classes_to_convert": Or( None, # List of tuples of two integers [[int, int]], error="Invalid value in config for 'grainstats.vetting.nearby_conversion_classes_to_convert', this" "needs to be a list of tuples of two integers", ), "class_touching_threshold": lambda n: n >= 0, "keep_largest_labelled_regions_classes": Or( None, # List of integers [int], error="Invalid value in config for 'grainstats.vetting.keep_largest_labelled_regions_classes', this" "needs to be a list of integers", ), "class_connection_point_thresholds": Or( None, # List of tuples: list[tuple[[tuple[int, int], tuple[int, int]]] [[[int, int], [int, int]]], error="Invalid value in config for 'grainstats.vetting.class_connection_point_thresholds', this" "needs to be a list of tuples of two tuples of two integers. Eg [((1, 2), (3, 4))]", ), }, }, "grainstats": { "run": Or( True, False, error="Invalid value in config for 'grainstats.run', valid values are 'True' or 'False'", ), "edge_detection_method": Or( "binary_erosion", "canny", ), "cropped_size": Or( float, int, ), "extract_height_profile": Or( True, False, error="Invalid value in config for 'grainstats.extract_height_profile'," "valid values are 'True' or 'False'", ), }, "disordered_tracing": { "run": Or( True, False, error="Invalid value in config for 'disordered_tracing.run', valid values are 'True' or 'False'", ), "min_skeleton_size": lambda n: n > 0.0, "pad_width": lambda n: n > 0.0, "mask_smoothing_params": { "gaussian_sigma": Or( float, int, None, ), "dilation_iterations": Or( int, None, ), "holearea_min_max": [ Or( int, float, None, error=( "Invalid value in config for 'disordered_tracing.mask_smoothing_params.holearea_min_max', valid values " "are int, float or null" ), ), ], }, "skeletonisation_params": { "method": Or( "zhang", "lee", "thin", "medial_axis", "topostats", error="Invalid value in config for 'disordered_tracing.skeletonisation_method'," "valid values are 'zhang', 'lee', 'thin', 'medial_axis', 'topostats'", ), "height_bias": lambda n: 0 < n <= 1, }, "pruning_params": { "method": Or( "topostats", error="Invalid value in config for 'disordered_tracing.pruning_method', valid values are 'topostats'", ), "max_length": lambda n: n >= 0, "method_values": Or("min", "median", "mid"), "method_outlier": Or("abs", "mean_abs", "iqr"), "height_threshold": Or(int, float, None), }, }, "nodestats": { "run": Or( True, False, error="Invalid value in config for 'nodestats.run', valid values are 'True' or 'False'", ), "node_joining_length": float, "node_extend_dist": float, "branch_pairing_length": float, "pair_odd_branches": bool, "pad_width": lambda n: n > 0.0, }, "ordered_tracing": { "run": Or( True, False, error="Invalid value in config for 'ordered_tracing.run', valid values are 'True' or 'False'", ), "ordering_method": Or( "nodestats", "original", error="Invalid value in config for 'ordered_tracing.ordering_method', valid values are 'nodestats' or 'original'", ), "pad_width": lambda n: n > 0.0, }, "splining": { "run": Or( True, False, error="Invalid value in config for 'splining.run', valid values are 'True' or 'False'", ), "method": Or( "spline", "rolling_window", error="Invalid value in config for 'splining.method', valid values are 'spline' or 'rolling_window'", ), "rolling_window_size": lambda n: n > 0.0, "spline_step_size": lambda n: n > 0.0, "spline_linear_smoothing": lambda n: n >= 0.0, "spline_circular_smoothing": lambda n: n >= 0.0, "spline_degree": int, # "cores": lambda n: n > 0.0, }, "curvature": { "run": Or( True, False, error="Invalid value in config for 'curvature.run', valid values are 'True' or 'False'", ), "colourmap_normalisation_bounds": [ Or( float, int, error="Invalid value in config for 'curvature.colourmap_normalisation_bounds', valid values" "are float or int", ) ], }, "plotting": { "run": Or( True, False, error="Invalid value in config for 'plotting.run', valid values are 'True' or 'False'", ), "style": And( str, Or( "topostats.mplstyle", str, Path, None, error="Invalid value in config for 'plotting.style', valid values are 'topostats.mplstyle' or None", ), ), "savefig_format": Or( None, str, error="Invalid value in config for plotting.savefig_format" "must be a value supported by Matplotlib.", ), "savefig_dpi": Or( None, "figure", lambda n: n > 0, error="Invalid value in config for plotting.savefig_dpi, valid" "values are 'figure' or floats", ), "image_set": Or( "all", "core", error="Invalid value in config for 'plotting.image_set', valid values " "are 'all' or 'core'", ), "pixel_interpolation": Or( None, "none", "bessel", "bicubic", "bilinear", "catrom", "gaussian", "hamming", "hanning", "hermite", "kaiser", "lanczos", "mitchell", "nearest", "quadric", "sinc", "spline16", "spline36", error="Invalid interpolation value. See https://matplotlib.org/stable/gallery/images_contours_and_fields/interpolation_methods.html for options.", ), "zrange": [float, int, None], "colorbar": Or( True, False, error="Invalid value in config for 'plotting.colorbar', valid values are 'True' or 'False'", ), "axes": Or( True, False, error="Invalid value in config plotting.for 'axes', valid values are 'True' or 'False'", ), "num_ticks": Or( [None, And(int, lambda n: n > 1)], error="Invalid value in config plotting.for 'num_ticks', valid values are 'null' or integers > 1", ), "cmap": Or( None, str, error="Invalid value in config for 'plotting.cmap', valid values are 'afmhot', 'nanoscope', " "'gwyddion' or values supported by Matplotlib", ), "mask_cmap": str, "histogram_log_axis": Or( True, False, error=( "Invalid value in config plotting histogram. For 'log_y_axis', valid values are 'True' or " "'False'" ), ), }, "summary_stats": { "run": Or( True, False, error="Invalid value in config for summary_stats.run, valid values are 'True' or 'False'", ), "config": Or( None, str, error=( "Invalid value in config for summary_stats.config, valid values are 'None' or a path to a " "config file." ), ), }, } ) PLOTTING_SCHEMA = Schema( { "extracted_channel": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'extracted_channel.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "pixels": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error="Invalid value in config 'pixels.image_type', valid values are 'binary' or 'non-binary'", ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "initial_median_flatten": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'initial_median_flatten.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "initial_tilt_removal": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'initial_tilt_removal.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "initial_quadratic_removal": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'initial_quadratic_removal.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "initial_scar_removal": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'initial_scar_removal.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "initial_zero_average_background": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'initial_zero_average_background.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "initial_nonlinear_polynomial_removal": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'initial_nonlinear_polynomial_removal.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "mask": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error="Invalid value in config 'mask.image_type', valid values are 'binary' or 'non-binary'", ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "masked_median_flatten": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'masked_median_flatten.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "masked_tilt_removal": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'masked_tilt_removal.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "masked_quadratic_removal": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'masked_quadratic_removal.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "masked_nonlinear_polynomial_removal": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'masked_nonlinear_polynomial_removal.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "secondary_scar_removal": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'masked_quadratic_removal.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "scar_mask": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'masked_quadratic_removal.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "final_zero_average_background": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'final_zero_average_background.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "gaussian_filtered": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'gaussian_filtered.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "z_threshed": { "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'z_threshold.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": True, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "mask_grains": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'mask_grains.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), "mask_cmap": str, }, "labelled_regions_01": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'labelled_regions_01.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), "mask_cmap": str, }, "tidied_border": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'tidied_border.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), "mask_cmap": str, }, "removed_noise": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'removed_noise.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "removed_small_objects": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'removed_small_objects.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "removed_objects_too_small_to_process": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'removed_objects_too_small_to_process.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "mask_overlay": { "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'mask_overlay.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": True, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "labelled_regions_02": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'labelled_regions_02.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "coloured_regions": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'coloured_regions.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "bounding_boxes": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'bounding_boxes.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "coloured_boxes": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'coloured_boxes.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), "mask_cmap": str, }, "grain_image": { "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'grain_image.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": False, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "grain_mask": { "image_type": Or( "binary", "non-binary", error=("Invalid value in config 'grain_mask.image_type', valid values " "are 'binary' or 'non-binary'"), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "grain_mask_image": { "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'grain_mask_image.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "orig_grain": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'coloured_boxes.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, }, "smoothed_grain": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'coloured_boxes.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, }, "skeleton": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'coloured_boxes.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": int, }, "pruned_skeleton": { "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'coloured_boxes.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": int, }, "branch_indexes": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'branch_indexes.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": int, }, "branch_types": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'coloured_boxes.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": int, }, "convolved_skeletons": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'convolved_skeleton.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": int, }, "node_centres": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'node_centres.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": int, }, "connected_nodes": { "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'node_branch_mask.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": int, }, "node_area_skeleton": { "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'node_area_skeleton.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": int, }, "node_branch_mask": { "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'node_branch_mask.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": int, }, "node_avg_mask": { "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'node_avg_mask.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, }, "node_line_trace": { "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'coloured_boxes.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, }, "ordered_traces": { "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'all_molecule_traces.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "trace_segments": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'all_molecule_traces.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "over_under": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'all_molecule_traces.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "all_molecules": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'coloured_boxes.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": int, }, "fitted_trace": { "filename": str, "title": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'coloured_boxes.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "mask_cmap": str, "core_set": bool, "savefig_dpi": int, }, "splined_trace": { "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'splined_trace.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "title": str, "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "curvature": { "image_type": Or( "binary", "non-binary", error=("Invalid value in config 'curvature.image_type', valid values " "are 'binary' or 'non-binary'"), ), "title": str, "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, "curvature_individual_grains": { "filename": str, "image_type": Or( "binary", "non-binary", error=( "Invalid value in config 'curvature_individual_grains.image_type', valid values " "are 'binary' or 'non-binary'" ), ), "title": str, "core_set": bool, "savefig_dpi": Or( lambda n: n > 0, "figure", error="Invalid value in config for 'dpi', valid values are 'figure' or > 0.", ), }, } ) SUMMARY_SCHEMA = Schema( { "base_dir": Path, "output_dir": Path, "csv_file": str, "savefig_format": Or( "png", "pdf", "svg", "tiff", "tif", error=("Invalid value in config 'savefig_format', valid values are 'png', 'pdf', 'svg', 'tiff' or 'tif'"), ), "var_to_label": Or( None, str, error="Invalid value in config for 'var_to_label', valid values are 'None' or a str", ), "image_id": str, "molecule_id": str, "hist": Or( True, False, error="Invalid value in config for 'hist', valid values are 'True' or 'False'", ), "bins": lambda n: n > 0, "stat": Or( "count", "frequency", "probability", "percent", "density", error=( "Invalid value in config 'stat', valid values are 'count', 'frequency', " "'probability', 'percent' or 'density'" ), ), "kde": Or( True, False, error="Invalid value in config for 'kde', valid values are 'True' or 'False'", ), "violin": Or( True, False, error="Invalid value in config for 'violin', valid values are 'True' or 'False'", ), "figsize": [lambda n: n > 0], "alpha": lambda n: n > 0, "palette": Or( "colorblind", "deep", "muted", "pastel", "bright", "dark", "Spectral", "Set2", error=( "Invalid value in config 'palette', valid values are 'colorblind', 'deep', " "'muted', 'pastel', 'bright', 'dark', 'Spectral' or 'Set2'" ), ), "stats_to_sum": [ Optional("area"), Optional("area_cartesian_bbox"), Optional("aspect_ratio"), Optional("bending_angle"), Optional("total_contour_length"), Optional("average_end_to_end_distance"), Optional("height_max"), Optional("height_mean"), Optional("height_median"), Optional("height_min"), Optional("max_feret"), Optional("min_feret"), Optional("radius_max"), Optional("radius_mean"), Optional("radius_median"), Optional("radius_min"), Optional("smallest_bounding_area"), Optional("smallest_bounding_length"), Optional("smallest_bounding_width"), Optional("volume"), ], } )