"""
Configuration management for BiaPy.
This module defines the Config class, which encapsulates all configuration options
for BiaPy workflows using a YACS CfgNode. It provides default values and hierarchical
organization for system, data, augmentation, model, loss, training, inference,
post-processing, and logging parameters. Utility functions are included for updating
dependent configuration variables after merging user-provided configs.
"""
import os
from yacs.config import CfgNode as CN
import copy
from typing import (
Dict,
)
[docs]
class Config:
"""
BiaPy configuration handler.
This class manages the hierarchical configuration for BiaPy experiments,
including system resources, problem specification, data loading, augmentation,
model architecture, loss functions, training, inference, post-processing, and
logging. It uses YACS CfgNode for flexible and robust configuration management.
Attributes
----------
_C : CN
The root YACS configuration node containing all experiment parameters.
"""
def __init__(self, job_dir: str, job_identifier: str):
"""
Initialize the Config object with default values.
Parameters
----------
job_dir : str
Directory where job outputs (results, checkpoints, logs) will be stored.
job_identifier : str
Unique identifier for the job (used in output paths).
"""
if "/" in job_identifier:
raise ValueError("Job name can not contain / character. Provided: {}".format(job_identifier))
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Config definition
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C = CN()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 1. System
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.SYSTEM = CN()
# Maximum number of CPUs to use. Set it to "-1" to not set a limit.
_C.SYSTEM.NUM_CPUS = -1
# Maximum number of workers to use. You can disable this option by setting 0. With a -1 the workers are calculated automatically.
_C.SYSTEM.NUM_WORKERS = -1
# Do not set it as its value will be calculated based in --gpu input arg
_C.SYSTEM.NUM_GPUS = 0
# Device to be used when GPU is NOT selected. Most commonly "cpu", but also potentially "mps",
# "xpu", "xla" or "meta".
_C.SYSTEM.DEVICE = "cpu"
# Math seed to generate random numbers. Used to ensure reproducibility in the results.
_C.SYSTEM.SEED = 0
# Pin CPU memory in DataLoader for more efficient (sometimes) transfer to GPU.
_C.SYSTEM.PIN_MEM = True
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2. Problem specification
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.PROBLEM = CN()
# Whether to check what changed to adapt the given input configuration to the newest. Basically to now what
# biapy.engine.check_configuration file's convert_old_model_cfg_to_current_version() function changes
_C.PROBLEM.PRINT_OLD_KEY_CHANGES = True
# Possible options: 'SEMANTIC_SEG', 'INSTANCE_SEG', 'DETECTION', 'DENOISING', 'SUPER_RESOLUTION',
# 'SELF_SUPERVISED', 'CLASSIFICATION' and 'IMAGE_TO_IMAGE'
_C.PROBLEM.TYPE = "SEMANTIC_SEG"
# Possible options: '2D' and '3D'
_C.PROBLEM.NDIM = "2D"
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2.1 Semantic segmentation problem specification
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.PROBLEM.SEMANTIC_SEG = CN()
# Class id to ignore when DATA.N_CLASSES > 2
_C.PROBLEM.SEMANTIC_SEG.IGNORE_CLASS_ID = 0
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2.2 Instance segmentation problem specification
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.PROBLEM.INSTANCE_SEG = CN()
# Type of instances expected. Options are: ["regular", "synapses"]
_C.PROBLEM.INSTANCE_SEG.TYPE = "regular"
#### For "regular" type of instances ####
# This variable defines the channels to be used to represent the instances. The approach follows a bottom-up setting,
# where the intermediate representations of the instances are learned by the model and then fused to create the final
# instances. The variable needs to be a list with the representations to be extracted from the instances.
# These are the options available:
# - 'F' stands for 'Foreground', it is a binary representation of each instance
# - 'B' stands for 'Background', it is a binary representation of the background, i.e. everything that is not an instance.
# - 'P' stands for 'Central part', the extreme case of the F channel, where only the center of mass, or the skeleton is
# represented. It may also be expressed as a heatmap.
# - 'C' stands for 'Contour', it is a binary representation of the countours of each instance.
# - 'H' stands for 'Horizontal distance' (HoVer-Net style). For each instance, the pixel/voxel value is the signed
# horizontal displacement to the centroid. When 'norm' is True (default) values are rescaled to [-1, 1]: leftmost
# pixel of the cell = -1, rightmost = +1, centroid column = 0. Background pixels are always 0.
# - 'V' stands for 'Vertical distance' (HoVer-Net style), same as 'H' along the vertical axis:
# top pixel = -1, bottom pixel = +1, centroid row = 0. Background = 0.
# - 'Z' stands for 'Depth distance' (HoVer-Net style), same as 'H' along the depth (z) axis. Only relevant for 3D data.
# - 'Gh', 'Gv', and 'Gz' stand for the x/y/z components of a flow field derived from a heat-diffusion potential
# (Cellpose strategy) or the per-cell EDT gradient (Omnipose strategy). Each component is a unit vector in [-1, 1];
# background is (0, 0[, 0]). Inspired by "Cellpose: a generalist algorithm for cellular segmentation"
# (https://www.nature.com/articles/s41592-020-01018-x) and "Omnipose" (https://www.nature.com/articles/s41467-022-32267-2).
# - 'Db' stands for 'Distance to the boundary'. For each foreground pixel the value is its Euclidean distance to
# the nearest background pixel (i.e. intra-cell distance from the cell boundary inward). After per-cell normalization
# ('norm'=True), boundary pixels map to 0 and the innermost pixel maps to 1. Background is always 0.
# - 'Dc' stands for 'Distance to the center'. For each foreground pixel the value is its Euclidean distance to
# the centroid (or skeleton) of its cell. The centroid pixel therefore has Dc = 0 (the minimum, most important value).
# Background is also 0. When 'norm' is True, values are rescaled per-cell to [0, 1].
# - 'Dn' stands for 'Distance to the closest neighbor'. For each foreground pixel the value reflects the proximity to
# the nearest other instance; isolated cells (no neighbor) are assigned 0. Background is 0.
# - 'D' stands for 'signed Distance field'. Foreground pixels hold the positive Euclidean distance to the nearest
# background pixel; background pixels hold the negative distance to the nearest foreground pixel. The field spans
# from negative (deep background) through 0 (boundary) to positive (deep interior). When 'norm' is True (default)
# the field is passed through tanh, mapping all values to (-1, 1). Because both foreground (+) and background (-)
# carry meaningful signal, the loss is computed on all pixels without masking.
# - 'R' stands for 'Radial distance', distances to boundaries measure how far each pixel is from its object's edge along fixed
# radial directions, with StarDist being the most prominent approach.
# - 'T' stands for 'Touching area', where touching regions between instances are highlighted.
# - 'A' stands for 'Affinities' and contains the affinity values for each dimension. Affinities represent images as graphs for
# segmentation, where each voxel is a node connected to neighbors by edges indicating shared object membership. In 3D, nodes
# link along x-, y-, and z-axes, yielding multiple affinity channels, commonly used in connectomics.
# - 'E' stands for 'Embeddings' and contains the embedding vectors for each pixel/voxel. Embedding-based approaches map each
# pixel in an input image to a point in an n-dimensional feature space (typically n=24), referred to as the pixel embedding.
# The goal is to ensure that embeddings from the same instance are close together, while embeddings from different instances
# are well separated. We grouped here all the channels involved in this process
#
#### For "synapse" type of instances ####
# Possible options:
# * 'F_pre' and 'F_post': each one is a binary representation of the presynaptic and postsynaptic sites, respectively.
# * 'F_pre', 'H', 'V', 'Z': 'F_pre' is a binary representation of the presynaptic sites, while 'H', 'V' and 'Z' are the horizontal,
# vertical and depth distances to the closest postsynaptic site, respectively. This setting is inspired by the paper
# "Automatic detection of synaptic partners in a whole-brain Drosophila electron microscopy data set"
# (https://www.nature.com/articles/s41592-021-01183-7).
#
_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS = ["B", "C"]
# Details for each channel. It must be a list with a unique element: a dict of dicts. The details can be only set for the following channels:
# - 'F' channel. Possible options:
# - 'erosion': int or list of ints, specifies the erosion size applied to the channel. Default: 0
# - 'dilation': int or list of ints, specifies the dilation size applied to the channel. Default: 0
# - 'B' channel. Possible options:
# - 'erosion': int or list of ints, specifies the erosion size applied to the channel. Default: 0
# - 'dilation': int or list of ints, specifies the dilation size applied to the channel. Default: 0
# - 'P' channel. Possible options:
# - 'type': str, specifies the reference used to define the channel. Options are 'centroid' or 'skeleton'. Default: 'centroid'
# - 'dilation': int or list of ints, specifies the dilation size applied to the channel. Default: 1
# - 'erosion': int or list of ints, specifies the erosion size applied to the channel. Useful for thinning skeletons,
# which are typically 2 pixels thick. Default: 0
# - 'C' channel. Possible options:
# - 'mode': str, specifies how contours are generated. Corresponds to the 'mode' argument of the
# find_boundaries function from scikit-image.
# More information at: https://scikit-image.org/docs/stable/api/skimage.segmentation.html#skimage.segmentation.find_boundaries.
# Options are 'thick', 'inner', 'outer', 'subpixel', and 'dense'. The 'dense' option labels as contour
# every pixel that is not part of the foreground. Default: 'thick'
# - 'H', 'V' and 'Z' channels. Possible options:
# - 'norm': bool, specifies whether signed displacements are normalized to [-1, 1] (centroid = 0). Default: True
# - 'act': str, specifies the activation function used in the model's final layer when this channel is selected.
# Options are 'linear', and 'sigmoid'. Default: ''
# Note: the loss mask for H/V/Z is derived automatically from a binary foreground channel (F, M, or B) in the GT
# when one is present; otherwise all pixels are included (background = 0 is a valid training target).
# - 'Gh', 'Gv' and 'Gz' channels. Possible options:
# - 'niter': int, number of iterations for the diffusion process (Cellpose strategy only). Default: 200
# - 'gradient_type': str, method to compute the gradients. Options are "cellpose" and "omnipose". Default: "cellpose"
# Note: the loss mask is derived automatically from the vector magnitude (foreground = unit-vector, background = zero).
# - 'Db' channel. Possible options:
# - 'val_type': str, to determine how to modify the distance values. Default: 'norm'. Options are:
# - 'raw': to leave the distances as they are calculated.
# - 'norm': to normalize the distances per cell to [0, 1] (boundary → 0, innermost pixel → 1).
# - 'discretize': to discretize the distances into bins.
# - 'bin_size': float, size of each bin when 'val_type' is 'discretize'. Default: 0.1
# - 'act': str, activation function to be used in the last layer of the model when this channel is selected.
# Options are: '', 'linear' and 'sigmoid'. Default: ''.
# - 'mask_values': bool, kept for compatibility but superseded: the loss mask prefers a binary foreground channel
# (F/M/B) to avoid excluding boundary pixels (Db=0). Falls back to (Db > 0) if no binary channel is present. Default: True
# - 'Dc' channel. Possible options:
# - 'type': str, specifies the reference used to calculate the distance. Options are 'centroid' or 'skeleton'.
# Default: 'centroid'
# - 'norm': bool, specifies whether distances are normalized per cell to [0, 1]. Default: True
# - 'mask_values': bool, kept for compatibility but superseded: the loss mask prefers a binary foreground channel
# (F/M/B) to correctly include the centroid pixel (Dc=0). Falls back to (Dc > 0) if no binary channel is present,
# which still misses the centroid — prefer pairing Dc with F, M, or B. Default: True
# - 'Dn' channel. Possible options:
# - 'closing_size': int, specifies the size of the closing operation applied to the combined distance map.
# Default: 0
# - 'norm': bool, specifies whether distances are normalized between 0 and 1. Default: True
# - 'mask_values': bool, kept for compatibility but superseded: the loss mask prefers a binary foreground channel
# (F/M/B) to include isolated cells (Dn=0). Falls back to (Dn > 0) if no binary channel is present. Default: True
# - 'decline_power': int, specifies the power applied to distances to control the rate of decline. Default: 3
# - 'D' channel. Possible options:
# - 'act': str, specifies the activation function used in the model's final layer when this channel is selected.
# Options are 'tanh' and 'linear'. Default: 'tanh'
# - 'alpha': int, specifies the scaling factor applied to background distances when 'act' is 'tanh'.
# Default: 1
# - 'beta': int, specifies the scaling factor applied to foreground distances when 'act' is 'tanh'.
# Default: 1
# - 'norm': bool, specifies whether distances are normalized between -1 and 1. Default: True
# - 'R' channel. Possible options:
# - 'nrays': int, specifies the number of rays used to represent radial distances.
# Default: 32 for 2D data and 96 for 3D data
# - 'norm': bool, specifies whether distances are normalized between 0 and 1. Default: True
# - 'mask_values': bool, kept for compatibility but superseded: the loss mask prefers a binary foreground channel
# (F/M/B) to avoid excluding near-boundary ray pixels (R≈0). Falls back to (R > 0) if no binary channel is present. Default: True
# - 'T' channel. Possible options:
# - 'thickness': int, specifies the thickness (in pixels) of the touching area. Default: 2
# - 'A' channel. Possible options:
# - 'z_affinities': list of int, specifies offsets along the z axis. Default: [1]
# - 'y_affinities': list of int, specifies offsets along the y axis. Default: [1]
# - 'x_affinities': list of int, specifies offsets along the x axis. Default: [1]
# - 'widen_borders': int, specifies the number of pixels used to widen affinity borders. Default: 1
# Note that 'z_affinities', 'y_affinities', and 'x_affinities' must be lists of equal length.
# To reproduce the paper "Superhuman Accuracy on the SNEMI3D Connectomics Challenge", use:
# 'z_affinities': [1, 2, 3, 4], 'y_affinities': [1, 3, 9, 27], and 'x_affinities': [1, 3, 9, 27]
# - 'E' channel. Possible options:
# - 'center_mode': str, specifies the center definition used for Gaussian seeds.
# Options are 'centroid' and 'medoid'. Default: 'centroid'
# - 'medoid_max_points': int, specifies the maximum number of points used when computing the medoid.
# Default: 10000
# For synapse type of instances, the options are:
# - 'F_pre' channel. Possible options:
# - 'dilation': int or list of ints, specifies the dilation size applied to the channel. Default: [1,3,3]
# - 'F_post' channel. Possible options:
# - 'dilation': int or list of ints, specifies the dilation size applied to the channel. Default: [1,3,3]
# - 'F_cleft' channel. Possible options:
# - 'dilation': int or list of ints, specifies the dilation size applied to the channel. Default: [1,3,3]
# - 'H', 'V' and 'Z' channels (synapse mode). Possible options:
# - 'norm': bool, if True signed displacements are normalized to [-1, 1]; if False raw physical distances are kept.
# Default: False (raw distances in physical units for synapse partner offsets)
# - 'act': str, specifies the activation function used in the model's final layer when this channel is selected.
# Options are '', 'linear', and 'sigmoid'. Default: ''
# - 'dilation': int or list of ints, specifies the dilation size applied to the channel. In the case of the synapses this
# will represent the area that will define the distance channels. Default: [3,25,25]
# Note: the loss mask for H/V/Z is derived automatically from a binary foreground channel (F_pre/F_post/F_cleft)
# when one is present; otherwise all pixels are included.
#
# For example:
# DATA_CHANNELS = ['F', 'C']
# DATA_CHANNELS_EXTRA_OPTS = [{'F': {'erosion': 2, 'dilation': 0}, 'C': {'mode': 'inner'}}]
_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS_EXTRA_OPTS = [{}]
# Losses to be applied to each channel. If not provided, the losses will be set automatically depending on the channel.
# The options are:
# - "bce"/"ce": binary cross entropy. Ref: https://pytorch.org/docs/stable/generated/torch.nn.BCEWithLogitsLoss.html
# - "l1"/"mae": mean absolute error. Ref: https://pytorch.org/docs/stable/generated/torch.nn.L1Loss.html
# - "mse": mean squared error. Ref: https://pytorch.org/docs/stable/generated/torch.nn.MSELoss.html
# - "triplet": triplet loss. Ref: https://pytorch.org/docs/stable/generated/torch.nn.TripletMarginLoss.html
_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS_LOSSES = []
# Whether to apply a rebalancing strategy to the loss function to give more importance to underrepresented pixels within the channels.
# The weights are calculated automatically based on the number of pixels of each class per batch and directly in the loss computation.
# For example, in the case of the "C" channel, which represents the contours of the instances, there are usually much less pixels representing
# contours than pixels representing the background. With this option activated, the loss will give more importance to contour pixels to help
# the model learn better to predict them.
_C.PROBLEM.INSTANCE_SEG.CLASS_REBALANCE_WITHIN_CHANNELS = True
# Information on how the channels are distributed in the model's output heads. It must be a list of list of ints, where each
# inner list contains the number of channels that are going to be predicted in the same head. If not provided, it will be set automatically
# with all the channels in one head, i.e. [DATA_CHANNELS]. For example, if "V", "H" and "Z" channels are in the same head, it is likely
# that they are representing distance maps and therefore the model will be able to learn them together. On the other hand, if "C" channel
# is in a different head than "H", "V" and "Z", it is likely that the model will be able to learn better the contours of the instances
# separately from the distance maps.
_C.PROBLEM.INSTANCE_SEG.CHANNELS_PER_HEAD_INFO = []
# Whether to use a different decoder for each head in the model.
_C.PROBLEM.INSTANCE_SEG.SEPARATED_DECODERS_PER_HEAD = False
# Weights to be applied to the channels. Notice that these weights are not applied directly to the loss, but to the predicted channels before
# calculating the loss. The length of the list must be equal to the number of channels.
# Notice that this is different from LOSS.WEIGHTS, which are used to apply weights to different losses.
_C.PROBLEM.INSTANCE_SEG.DATA_CHANNEL_WEIGHTS = (1, 1)
# Whether to add an extra weight map to the loss calculation to focus on the borders between instances. Different weighting maps
# can be defined. Options: ["unet-like", ""]
_C.PROBLEM.INSTANCE_SEG.BORDER_EXTRA_WEIGHTS = ""
# Defines how the instances are created. Options:
# - "watershed" to use watershed algorithm
# - "agglomeration" to use agglomeration algorithm
# - "stardist" to use stardist algorithm
# - "embeddings" to use embedding-based clustering algorithms
_C.PROBLEM.INSTANCE_SEG.INSTANCE_CREATION_PROCESS = ""
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2.2.1 Watershed options for instance segmentation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Options for marker-controlled watershed
_C.PROBLEM.INSTANCE_SEG.WATERSHED = CN()
# List of the channels to be used for seed creation. If not provided will be automatically set based on
# 'PROBLEM.INSTANCE_SEG.DATA_CHANNELS'.
_C.PROBLEM.INSTANCE_SEG.WATERSHED.SEED_CHANNELS = []
# Thresholds for the seed channels. If not provided will be automatically set with "auto" for each channel.
# If set it must have same length than 'PROBLEM.INSTANCE_SEG.WATERSHED.SEED_CHANNELS'. Options:
# - A float between 0 and 1 to threshold each channel
# - "auto" to automatically define a value by applying an Otsu thresholding
_C.PROBLEM.INSTANCE_SEG.WATERSHED.SEED_CHANNELS_THRESH = []
# Defines the topographic surface to grow the seeds. If not provided will be automatically set based on
# 'PROBLEM.INSTANCE_SEG.DATA_CHANNELS'. If defined it must be a channel name, e.g. "B" or "C".
_C.PROBLEM.INSTANCE_SEG.WATERSHED.TOPOGRAPHIC_SURFACE_CHANNEL = ""
# Channel to be used for growth mask creation. If not provided will be automatically set based on
# 'PROBLEM.INSTANCE_SEG.DATA_CHANNELS'. Options:
# - A list of channel names, e.g. ["B"], ["C"] or ["B", "C"]. The channels must be in 'PROBLEM.INSTANCE_SEG.DATA_CHANNELS'
# - "auto" to automatically create it based on the selected channels ('PROBLEM.INSTANCE_SEG.DATA_CHANNELS')
_C.PROBLEM.INSTANCE_SEG.WATERSHED.GROWTH_MASK_CHANNELS = []
# Thresholds for the growth mask channels. If not provided will be automatically set with "auto" for each channel.
# If set it must have same length than 'PROBLEM.INSTANCE_SEG.WATERSHED.GROWTH_MASK_CHANNELS'. Options:
# - A float between 0 and 1 to threshold each channel
# - "auto" to automatically define a value depending on the channels provided
_C.PROBLEM.INSTANCE_SEG.WATERSHED.GROWTH_MASK_CHANNELS_THRESH = []
# Sequence of string to determine the morphological filters to apply to instance seeds. They will be done in that order.
# Possible options 'dilate' and 'erode'. E.g. ['erode','dilate'] to erode first and dilate later.
_C.PROBLEM.INSTANCE_SEG.WATERSHED.SEED_MORPH_SEQUENCE = []
# Sequence of ints to determine the radius of the erosion or dilation for instance seeds
_C.PROBLEM.INSTANCE_SEG.WATERSHED.SEED_MORPH_RADIUS = []
# To erode and dilate the foreground mask before using marker controlled watershed. The idea is to remove the small holes
# that may be produced so the instances grow without them
_C.PROBLEM.INSTANCE_SEG.WATERSHED.ERODE_AND_DILATE_GROWTH_MASK = False
# Radius to erode the foreground mask
_C.PROBLEM.INSTANCE_SEG.WATERSHED.FORE_EROSION_RADIUS = 5
# Radius to dilate the foreground mask
_C.PROBLEM.INSTANCE_SEG.WATERSHED.FORE_DILATION_RADIUS = 5
# Whether to save watershed check files
_C.PROBLEM.INSTANCE_SEG.WATERSHED.DATA_CHECK_MW = False
# Size of small objects to be removed before doing watershed
_C.PROBLEM.INSTANCE_SEG.WATERSHED.DATA_REMOVE_SMALL_OBJ_BEFORE = 10
# Whether to remove objects before watershed
_C.PROBLEM.INSTANCE_SEG.WATERSHED.DATA_REMOVE_BEFORE_MW = False
# Whether to apply or not the watershed to create instances slice by slice in a 3D problem. This can solve instances invading
# others if the objects in Z axis overlap too much.
_C.PROBLEM.INSTANCE_SEG.WATERSHED.BY_2D_SLICES = False
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2.2.2 Stardist-like post-processing options for instance segmentation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Options for stardist-kind instance creation
_C.PROBLEM.INSTANCE_SEG.STARDIST = CN()
# Probability threshold to consider a pixel/voxel as a potential instance center
_C.PROBLEM.INSTANCE_SEG.STARDIST.PROB_THRESH = 0.4
# Non-maximum suppression IoU threshold to filter overlapping instance candidates
_C.PROBLEM.INSTANCE_SEG.STARDIST.NMS_IOU_THRESH = 0.3
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2.2.3 Cellpose/Omnipose-like post-processing options for instance segmentation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Options for flow-field-based instance creation from Gv/Gh/[Gz] channels.
# Inspired by the work:
# References:
# "Cellpose: a generalist algorithm for cellular segmentation"
# [link]: https://www.nature.com/articles/s41592-020-01018-x
# "Omnipose: a high-precision morphology-independent solution for bacterial cell segmentation"
# [link]: https://www.nature.com/articles/s41592-022-01639-4
_C.PROBLEM.INSTANCE_SEG.CELLPOSE = CN()
# Post-processing strategy to use for flow-field-based instance creation. Options:
# - 'cellpose': Euler integration with time-suppressed steps (dt/(t+1)) followed by
# histogram peak detection and nearest-peak assignment. A flow consistency check then
# removes instances whose predicted flow diverges from a centroid-pointing approximation.
# Suited for Cellpose-style flows (heat-diffusion potential gradient).
# - 'omnipose': Euler integration with constant step size followed by DBSCAN clustering
# on convergence positions. The flow consistency check is skipped. Suited for
# Omnipose-style flows (per-cell EDT gradient), which converge precisely to the
# cell skeleton rather than a centroid.
_C.PROBLEM.INSTANCE_SEG.CELLPOSE.TYPE = "cellpose"
# Foreground probability threshold. Pixels/voxels with a predicted foreground probability
# above this value are considered foreground and will be traced through the flow field.
# Applies when a dedicated binary channel ('F', 'M', or 'B') is present in DATA_CHANNELS.
_C.PROBLEM.INSTANCE_SEG.CELLPOSE.FG_THRESH = 0.5
# Flow-consistency threshold to discard spurious instances after Euler integration.
# Measured as mean cosine-similarity error (0 = perfect, 2 = opposite direction).
# Instances with error > this threshold are removed. Set to 0 to disable.
_C.PROBLEM.INSTANCE_SEG.CELLPOSE.FLOW_THRESHOLD = 0.4
# Number of Euler integration steps used to trace each foreground pixel through the
# flow field until it converges to an attractor.
_C.PROBLEM.INSTANCE_SEG.CELLPOSE.N_STEPS = 200
# Step size (dt) for each Euler integration step.
_C.PROBLEM.INSTANCE_SEG.CELLPOSE.DT = 1.0
# Whether to use Cellpose-style step suppression (dt / (t+1)) that slows each step as
# integration progresses, improving convergence for noisy flow fields.
_C.PROBLEM.INSTANCE_SEG.CELLPOSE.SUPPRESSED = True
# Minimum number of pixels in a connected component to be kept as a valid instance.
# Smaller objects are discarded after clustering.
_C.PROBLEM.INSTANCE_SEG.CELLPOSE.MIN_SIZE = 15
# Maximum pixel distance from a pixel's convergence position to a valid attractor peak.
# Pixels whose convergence position falls farther than this from any peak are discarded.
_C.PROBLEM.INSTANCE_SEG.CELLPOSE.MAX_CLUSTER_DIST = 5.0
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2.2.4 EmbedSeg-like post-processing options for instance segmentation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Options for embedding-based clustering instance creation. They are inspired by the work:
# Reference:
# "EmbedSeg: Embedding-based Instance Segmentation for Biomedical Microscopy Data"
# [link]: https://www.sciencedirect.com/science/article/pii/S1361841522001700
# Code adapted from:
# Embedseg: https://github.com/juglab/EmbedSeg
_C.PROBLEM.INSTANCE_SEG.EMBEDSEG = CN()
# Foreground threshold for seediness map to consider pixels for clustering.
_C.PROBLEM.INSTANCE_SEG.EMBEDSEG.SEED_THRESH = 0.5
# Minimum number of foreground pixels required to perform clustering.
_C.PROBLEM.INSTANCE_SEG.EMBEDSEG.MIN_MASK_SUM = 0
# Minimum number of unclustered foreground pixels to continue clustering.
_C.PROBLEM.INSTANCE_SEG.EMBEDSEG.MIN_UNCLUSTERED_SUM = 0
# Minimum size of objects to be considered valid. Objects smaller than this will be ignored.
_C.PROBLEM.INSTANCE_SEG.EMBEDSEG.MIN_OBJECT_SIZE = 100
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2.2.5 Synapse-specific options for instance segmentation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#### For "synapses" type of instances (only available for 3D H5/Zarr data) ####
_C.PROBLEM.INSTANCE_SEG.SYNAPSES = CN()
# Method to create the points from the synapse prediction (in "F_pre" + "F_post" setting). Options are:
# - 'peak_local_max' to use the skimage.feature.peak_local_max function to create the points
# - 'blob_log' to use the skimage.feature.blob_log function to create the points
_C.PROBLEM.INSTANCE_SEG.SYNAPSES.POINT_CREATION_FUNCTION = "peak_local_max"
# The minimal allowed distance separating peaks. To find the maximum number of peaks, use min_distance=1.
_C.PROBLEM.INSTANCE_SEG.SYNAPSES.PEAK_LOCAL_MAX_MIN_DISTANCE = 1
# Whether the threshold are going to be set as automaticaly (with Otsu thresholding) or manually.
# Options available:
# * 'auto' to decide the threshold to be applied by measuring it with Otsu
# * 'manual' to set a fixed threshold defined by 'PROBLEM.INSTANCE_SEG.SYNAPSES.MIN_TH_TO_BE_PEAK'
# * 'relative_by_patch' to use 'PROBLEM.INSTANCE_SEG.SYNAPSES.MIN_TH_TO_BE_PEAK' but relative to the maximum value in the predicted patch
# data. More info in https://scikit-image.org/docs/0.25.x/api/skimage.feature.html#skimage.feature.peak_local_max and
# https://scikit-image.org/docs/0.23.x/api/skimage.feature.html#skimage.feature.blob_log (see 'threshold_rel' argument description)
# * 'relative' to use 'PROBLEM.INSTANCE_SEG.SYNAPSES.MIN_TH_TO_BE_PEAK' but relative to the maximum value in the whole predicted data.
# More info in https://scikit-image.org/docs/0.25.x/api/skimage.feature.html#skimage.feature.peak_local_max and
# https://scikit-image.org/docs/0.23.x/api/skimage.feature.html#skimage.feature.blob_log (see 'threshold_rel' argument description)
_C.PROBLEM.INSTANCE_SEG.SYNAPSES.TH_TYPE = "auto"
# Minimun value to consider a point as a peak. Corresponds to 'threshold_abs' argument of the function
# 'peak_local_max' of skimage.feature
_C.PROBLEM.INSTANCE_SEG.SYNAPSES.MIN_TH_TO_BE_PEAK = 0.2
# Corresponds to 'exclude_border' argument of 'peak_local_max' or 'blob_log' function of skimage. If True it will exclude
# peaks from the border of the image to avoid partial detection.
_C.PROBLEM.INSTANCE_SEG.SYNAPSES.EXCLUDE_BORDER = False
# Corresponds to 'min_sigma' argument of 'blob_log' function. It is the minimum standard deviation for Gaussian kernel.
# Keep this low to detect smaller blobs. The standard deviations of the Gaussian filter are given for each axis as a
# sequence, or as a single number, in which case it is equal for all axes.
_C.PROBLEM.INSTANCE_SEG.SYNAPSES.BLOB_LOG_MIN_SIGMA = 5
# Corresponds to 'max_sigma' argument of 'blob_log' function. It is the maximum standard deviation for Gaussian kernel.
# Keep this high to detect larger blobs. The standard deviations of the Gaussian filter are given for each axis as a
# sequence, or as a single number, in which case it is equal for all axes.
_C.PROBLEM.INSTANCE_SEG.SYNAPSES.BLOB_LOG_MAX_SIGMA = 10
# Corresponds to 'num_sigma' argument of 'blob_log' function. The number of intermediate values of standard deviations
# to consider between min_sigma and max_sigma.
_C.PROBLEM.INSTANCE_SEG.SYNAPSES.BLOB_LOG_NUM_SIGMA = 2
# For removing close points detected during synapse prediction
_C.PROBLEM.INSTANCE_SEG.SYNAPSES.REMOVE_CLOSE_PRE_POINTS_RADIUS = 0
_C.PROBLEM.INSTANCE_SEG.SYNAPSES.REMOVE_CLOSE_POST_POINTS_RADIUS = 0
# If this is activated the post points will be remove not only looking the distance between them but the must lay in the same mask.
# For creating this mask there can be a few options:
# * Implemented: By creating instances binarizing the predictions (using PROBLEM.INSTANCE_SEG.SYNAPSES.MIN_TH_TO_BE_PEAK) and applying
# a connected-components
# * TODO: by looking at external neuron segmentation
_C.PROBLEM.INSTANCE_SEG.SYNAPSES.REMOVE_CLOSE_POINTS_RADIUS_BY_MASK = False
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2.3 Detection problem specification
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.PROBLEM.DETECTION = CN()
# Shape of the ellipse that will be used to dilate the central point created from the CSV file. 0 to not dilate and only create a 3x3 square.
# The value is the radius of the ellipse in pixels. If an integer is given, the shape will be a ball with the given side length.
# If a list is given, the shape will be a hyperball with the given side lengths. List order is (y,x) or (z,y,x) for 2D and 3D respectively.
# For example [1, 2, 3] will result in an ellipse with a radius of 1 in the first dimension, 2 in the second and 3 in the third.
_C.PROBLEM.DETECTION.CENTRAL_POINT_DILATION = [2]
_C.PROBLEM.DETECTION.CHECK_POINTS_CREATED = True
# Whether to save watershed check files
_C.PROBLEM.DETECTION.DATA_CHECK_MW = False
# Whether to apply a rebalancing strategy to the loss function to give more importance to underrepresented pixels within the channels.
# The weights are calculated automatically based on the number of pixels of each class per batch and directly in the loss computation.
# In the specific case of detection, where there are usually much less pixels representing the center of the objects to detect than
# background pixels, with this option activated, the loss will give more importance to the pixels representing the center of the objects
# to help the model learn better to predict them.
_C.PROBLEM.DETECTION.CLASS_REBALANCE_WITHIN_CHANNELS = True
# Weights to be applied to the channels when doing detection with classes. Notice that these weights are not applied directly to the loss,
# but to the predicted channels before calculating the loss. The length of the list must be equal to the number of channels.
# Notice that this is different from LOSS.WEIGHTS, which are used to apply weights to different losses.
_C.PROBLEM.DETECTION.DATA_CHANNEL_WEIGHTS = (1, 1)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2.4 Denoising problem specification
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Based Noise2Void paper: https://arxiv.org/abs/1811.10980
_C.PROBLEM.DENOISING = CN()
# This variable corresponds to n2v_perc_pix from Noise2Void. It explanation is as follows: for faster training multiple
# pixels per input patch can be manipulated. In our experiments we manipulated about 0.198% of the input pixels per
# patch. For a patch size of 64 by 64 pixels this corresponds to about 8 pixels. This fraction can be tuned via this variable
_C.PROBLEM.DENOISING.N2V_PERC_PIX = 0.198
# This variable corresponds to n2v_manipulator from Noise2Void. Most pixel manipulators will compute the replacement value based
# on a neighborhood and this variable controls how to do that
_C.PROBLEM.DENOISING.N2V_MANIPULATOR = "uniform_withCP"
# This variable corresponds to n2v_neighborhood_radius from Noise2Void. Size of the neighborhood to compute the replacement
_C.PROBLEM.DENOISING.N2V_NEIGHBORHOOD_RADIUS = 5
# To apply a structured mask as is proposed in Noise2Void to alleviate the limitation of the method of not removing effectively
# the structured noise (section 4.4 of their paper).
_C.PROBLEM.DENOISING.N2V_STRUCTMASK = False
# Whether to load ground truth data in denoising
_C.PROBLEM.DENOISING.LOAD_GT_DATA = False
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2.4 Super-resolution problem specification
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.PROBLEM.SUPER_RESOLUTION = CN()
# Upscaling to be done to the input images on every dimension. Examples: (2,2) in 2D or (2,2,2) in 3D.
_C.PROBLEM.SUPER_RESOLUTION.UPSCALING = ()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2.5 Self-supervised problem specification
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.PROBLEM.SELF_SUPERVISED = CN()
# Pretext task to do. Options are as follows:
# - 'crappify': crappifies input image by adding Gaussian noise and downsampling and upsampling it so the resolution
# gets worsen. Then, the model is trained to recover the original images.
# - 'masking': mask input image and the model needs to recover the original image. This option can only
# be done with 'mae' transformer. This strategy follows the one proposed in:
# Masked Autoencoders Are Scalable Vision Learners (https://arxiv.org/pdf/2111.06377.pdf)
_C.PROBLEM.SELF_SUPERVISED.PRETEXT_TASK = "crappify"
# Downsizing factor to reshape the image. It will be downsampled and upsampled again by this factor so the
# quality of the image is worsens
_C.PROBLEM.SELF_SUPERVISED.RESIZING_FACTOR = 4
# Number between [0, 1] indicating the std of the Gaussian noise N(0,std).
_C.PROBLEM.SELF_SUPERVISED.NOISE = 0.2
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2.6 Image-to-image problem specification
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.PROBLEM.IMAGE_TO_IMAGE = CN()
# Information on how the channels are distributed in the model's output heads. It must be a list of list of ints, where each
# inner list contains the number of channels that are going to be predicted in the same head.
_C.PROBLEM.IMAGE_TO_IMAGE.CHANNELS_PER_HEAD_INFO = []
# Whether to use a different decoder for each head in the model.
_C.PROBLEM.IMAGE_TO_IMAGE.SEPARATED_DECODERS_PER_HEAD = False
# Expected output channels to be predicted by the model.
_C.PROBLEM.IMAGE_TO_IMAGE.OUTPUT_CHANNELS = 1
# To use a custom data loader to load a random image from each image sample folder. The data needs to be structured
# in an special way, that is, instead of having images in the training/val folder a folder for each sample is expected,
# where in each of those different versions of the same data sample will be placed. Visit the following tutorial
# for a real use case and a more detailed description:
# - https://biapy.readthedocs.io/en/latest/tutorials/image-to-image/lightmycells.html
_C.PROBLEM.IMAGE_TO_IMAGE.MULTIPLE_RAW_ONE_TARGET_LOADER = False
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3. Dataset
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.DATA = CN()
# Save all data of a generator in the given path.
_C.DATA.CHECK_GENERATORS = False
# _C.PROBLEM.NDIM='2D' -> _C.DATA.PATCH_SIZE=(y,x,c) ; _C.PROBLEM.NDIM='3D' -> _C.DATA.PATCH_SIZE=(z,y,x,c)
_C.DATA.PATCH_SIZE = (256, 256, 1)
# Number of classes including the background class (that should be using 0 label)
_C.DATA.N_CLASSES = 2
# Whether to reshape the dimensions that does not satisfy the patch shape selected by padding it with reflect.
_C.DATA.REFLECT_TO_COMPLETE_SHAPE = True
# If 'DATA.PATCH_SIZE' selected has 3 channels, e.g. RGB images are expected, so will force grayscale images to be
# converted into RGB (e.g. in ImageNet some of the images are grayscale)
_C.DATA.FORCE_RGB = False
# If filtering is done, with any of DATA.*.FILTER_SAMPLES.* variables, this will decide how this filtering will be done:
# * True: apply filter image by image.
# * False: apply filtering sample by sample. Each sample represents a patch within an image.
_C.DATA.FILTER_BY_IMAGE = False
# Determines whether to save filtered images. If 'DATA.FILTER_BY_IMAGE' is enabled, two subfolders will be created: one for
# filtered images and another for non-filtered images. Otherwise, no subfolders will be created, and the images will
# display filtered patches as black (all zero values) while retaining original patch values in non-filtered areas.
_C.DATA.SAVE_FILTERED_IMAGES = False
# Number of filtered images to save. Only work when 'DATA.SAVE_FILTERED_IMAGES' is True
_C.DATA.SAVE_FILTERED_IMAGES_NUM = 3
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3.1 Normalization options for the data
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.DATA.NORMALIZATION = CN()
# Whether to apply or not a percentile clipping before normalizing the data
_C.DATA.NORMALIZATION.PERC_CLIP = CN()
_C.DATA.NORMALIZATION.PERC_CLIP.ENABLE = False
# Lower and upper bound for percentile clip. Must be set when DATA.NORMALIZATION.PERC_CLIP.ENABLE = 'True'
_C.DATA.NORMALIZATION.PERC_CLIP.LOWER_PERC = -1.0
_C.DATA.NORMALIZATION.PERC_CLIP.UPPER_PERC = -1.0
# Lower and upper values to clip. If these are provided the percentiles are not calculated based on
# 'DATA.NORMALIZATION.PERC_CLIP.LOWER_PERC' and 'DATA.NORMALIZATION.PERC_CLIP.UPPER_PERC'
_C.DATA.NORMALIZATION.PERC_CLIP.LOWER_VALUE = [-1.0]
_C.DATA.NORMALIZATION.PERC_CLIP.UPPER_VALUE = [-1.0]
# Normalization type to use. Possible options:
# 'div' to divide values from 0/255 (or 0/65535 if uint16) in [0,1] range
# 'scale_range' same as 'div' but scaling the range to [0-max] and then dividing by the maximum value of the data
# and not by 255 or 65535
# 'zero_mean_unit_variance' to substract the mean and divide by std.
_C.DATA.NORMALIZATION.TYPE = "zero_mean_unit_variance"
# Custom normalization variables: mean and std (they are calculated if not provided)
_C.DATA.NORMALIZATION.ZERO_MEAN_UNIT_VAR = CN()
_C.DATA.NORMALIZATION.ZERO_MEAN_UNIT_VAR.MEAN_VAL = [-1.0]
_C.DATA.NORMALIZATION.ZERO_MEAN_UNIT_VAR.STD_VAL = [-1.0]
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3.2 Training data options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.DATA.TRAIN = CN()
# Whether to check if the data mask contains correct values, e.g. same classes as defined
_C.DATA.TRAIN.CHECK_DATA = True
_C.DATA.TRAIN.IN_MEMORY = True
_C.DATA.TRAIN.PATH = os.path.join("user_data", "train", "x")
_C.DATA.TRAIN.GT_PATH = os.path.join("user_data", "train", "y")
# Whether your input Zarr contains the raw images and labels together or not. Use 'DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_RAW_PATH'
# and 'DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_GT_PATH' to determine the tag to find within the Zarr
_C.DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA = False
# Paths to the raw and gt within the Zarr file. Only used when 'DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA' is True.
# E.g. 'volumes.raw' for raw and 'volumes.labels.neuron_ids' for GT path.
_C.DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_RAW_PATH = ""
_C.DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_GT_PATH = ""
# For synapse detection. The information must be stored as CREMI dataset (https://cremi.org/data/)
# Path within the file where the ``ids`` are stored. Reference in CREMI: ``annotations/ids``
_C.DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_ID_PATH = "annotations.ids"
# Path within the file where the ``types`` are stored (not used). Reference in CREMI: ``annotations/types``
# _C.DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_TYPES_PATH = "annotations.types"
# Path within the file where the ``partners`` are stored. Reference in CREMI: ``annotations/partners``
_C.DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_PARTNERS_PATH = "annotations.presynaptic_site.partners"
# Path within the file where the ``locations`` are stored. Reference in CREMI: ``annotations/locations``
_C.DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_LOCATIONS_PATH = "annotations.locations"
# Path within the file where the ``resolution`` is stored. Reference in CREMI: ``["volumes/raw"].attrs["offset"]``
_C.DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_RESOLUTION_PATH = 'volumes.raw'
# File to load/save data prepared with the appropiate channels in a instance segmentation problem.
# E.g. _C.PROBLEM.TYPE ='INSTANCE_SEG' and _C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS != 'B'
_C.DATA.TRAIN.INSTANCE_CHANNELS_MASK_DIR = os.path.join(
"user_data", "train", "y_" + "".join(_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS)
)
# Path to load/save detection masks prepared.
_C.DATA.TRAIN.DETECTION_MASK_DIR = os.path.join("user_data", "train", "y_detection_masks")
# Path to load/save SSL target prepared.
_C.DATA.TRAIN.SSL_SOURCE_DIR = os.path.join("user_data", "train", "x_ssl_source")
# Percentage of overlap in (y,x)/(z,y,x) when cropping validation. Set to 0 to calculate the minimun overlap.
# The values must be floats between range [0, 1). It needs to be a 2D tuple when using _C.PROBLEM.NDIM='2D' and
# 3D tuple when using _C.PROBLEM.NDIM='3D'
_C.DATA.TRAIN.OVERLAP = (0, 0)
# Padding to be done in (y,x)/(z,y,x) when reconstructing train data. Useful to avoid patch 'border effect'.
_C.DATA.TRAIN.PADDING = (0, 0)
# Train data resolution. It is not completely necessary but when configured it is taken into account when
# performing some augmentations, e.g. cutout. If defined it need to be (y,x)/(z,y,x) and needs to be to be a 2D
# tuple when using _C.PROBLEM.NDIM='2D' and 3D tuple when using _C.PROBLEM.NDIM='3D'
_C.DATA.TRAIN.RESOLUTION = (-1,)
# Order of the axes of the image when using Zarr/H5 images in train data.
_C.DATA.TRAIN.INPUT_IMG_AXES_ORDER = "TZCYX"
# Order of the axes of the mask when using Zarr/H5 images in train data.
_C.DATA.TRAIN.INPUT_MASK_AXES_ORDER = "TZCYX"
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3.2.1 Training data filtering options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# DATA.TRAIN.FILTER_SAMPLES allows removing training images by the conditions based on their properties. When using Zarr each patch within the Zarr will be
# processed and will not depend on 'DATA.FILTER_BY_IMAGE' variable.
# Its three variables (PROPS, VALUES and SIGNS) define a set of conditions to remove the images from the training set. If an image satisfies any of the
# conditions, the image won't be used for training.
#
# In PROPS, we define the property to look at to establish the condition. The available properties are: ['foreground', 'mean', 'min', 'max',
# 'target_mean', 'target_min', 'target_max', 'diff', 'diff_by_min_max_ratio', 'diff_by_target_min_max_ratio'].
#
# * 'foreground' is defined as the percentage of pixels/voxels corresponding to the foreground mask. This option is only valid for
# SEMANTIC_SEG, INSTANCE_SEG and DETECTION.
# * 'mean' is defined as the mean intensity value of the raw image inputs.
# * 'min' is defined as the min intensity value of the raw image inputs.
# * 'max' is defined as the max intensity value of the raw image inputs.
# * 'diff' is defined as the difference between ground truth and raw images. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'diff_by_min_max_ratio' is defined as the difference between ground truth and raw images multiplied by the ratio between raw image max and min. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'target_mean' is defined as the mean intensity value of the raw image targets. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'target_min' is defined as the min intensity value of the raw image targets. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'target_max' is defined as the max intensity value of the raw image targets. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'diff_by_target_min_max_ratio' is defined as the difference between ground truth and raw images multiplied by the ratio between ground truth image max and min. Available for all workflows but SELF_SUPERVISED and DENOISING.
#
# With VALUES and SIGNS, we define the specific values and the comparison operators of each property, respectively.
# The available operators are: ['gt', 'ge', 'lt', 'le'], that corresponds to "greather than" (or ">"), "greather equal" (or ">="), "less than" (or "<"),
# and "less equal" (or "<=").
#
# Here you have a full example of this filtering:
# If you want to remove those samples that have intensity values lower than 0.00001 and a mean average greater than 100 you should
# declare the above three variables as follows (notice you need to know the image data type in advance):
# _C.DATA.TRAIN.FILTER_SAMPLES.PROPS = [['foreground','mean']]
# _C.DATA.TRAIN.FILTER_SAMPLES.VALUES = [[0.00001, 100]]
# _C.DATA.TRAIN.FILTER_SAMPLES.SIGNS = [['lt', 'gt']]
# You can also concatenate more restrictions and they will be applied in order. For instance, if you want to filter those
# samples with a maximum intensity value greater than 1000, and do that before the condition described above, you can define the
# variables this way:
# _C.DATA.TRAIN.FILTER_SAMPLES.PROPS = [['max'], ['foreground','mean']]
# _C.DATA.TRAIN.FILTER_SAMPLES.VALUES = [[1000], [0.00001, 100]]
# _C.DATA.TRAIN.FILTER_SAMPLES.SIGNS = [['gt'], ['lt', 'gt']]
# This way, the images will be removed by 'max' and then by 'foreground' and 'mean'
_C.DATA.TRAIN.FILTER_SAMPLES = CN()
# Whether to enable or not the filtering by properties
_C.DATA.TRAIN.FILTER_SAMPLES.ENABLE = False
# List of lists of properties to apply a filter. Available properties are: ['foreground', 'mean', 'min', 'max',
# 'target_mean', 'target_min', 'target_max', 'diff', 'diff_by_min_max_ratio', 'diff_by_target_min_max_ratio']
_C.DATA.TRAIN.FILTER_SAMPLES.PROPS = []
# List of ints/float that represent the values of the properties listed in 'DATA.TRAIN.FILTER_SAMPLES.PROPS'
# that the images need to satisfy to not be dropped.
_C.DATA.TRAIN.FILTER_SAMPLES.VALUES = []
# List of list of signs to do the comparison. Options: ['gt', 'ge', 'lt', 'le'] that corresponds to "greather than", e.g. ">",
# "greather equal", e.g. ">=", "less than", e.g. "<", and "less equal" e.g. "<=" comparisons.
_C.DATA.TRAIN.FILTER_SAMPLES.SIGNS = []
# Whether to normalize the samples before comparison
_C.DATA.TRAIN.FILTER_SAMPLES.NORM_BEFORE = False
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3.3 Validation data options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.DATA.VAL = CN()
# Enabling distributed evaluation (recommended during training)
_C.DATA.VAL.DIST_EVAL = True
# Whether to create validation data from training set or read it from a directory
_C.DATA.VAL.FROM_TRAIN = True
# Use a cross validation strategy instead of just split the train data in two
_C.DATA.VAL.CROSS_VAL = False
# Number of folds. Used when _C.DATA.VAL.CROSS_VAL == True
_C.DATA.VAL.CROSS_VAL_NFOLD = 5
# Number of the fold to choose as validation. Used when _C.DATA.VAL.CROSS_VAL == True
_C.DATA.VAL.CROSS_VAL_FOLD = 1
# Percentage of the training data used as validation. Used when _C.DATA.VAL.FROM_TRAIN = True and _C.DATA.VAL.CROSS_VAL == False
_C.DATA.VAL.SPLIT_TRAIN = 0.1
# Create the validation data with random images of the training data. Used when _C.DATA.VAL.FROM_TRAIN = True
_C.DATA.VAL.RANDOM = True
# Used when _C.DATA.VAL.FROM_TRAIN = False, as DATA.VAL.FROM_TRAIN = True always implies DATA.VAL.IN_MEMORY = True
_C.DATA.VAL.IN_MEMORY = True
# Path to the validation data. Used when _C.DATA.VAL.FROM_TRAIN = False
_C.DATA.VAL.PATH = os.path.join("user_data", "val", "x")
# Path to the validation data mask. Used when _C.DATA.VAL.FROM_TRAIN = False
_C.DATA.VAL.GT_PATH = os.path.join("user_data", "val", "y")
# Whether your input Zarr contains the raw images and labels together or not. Use 'DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_RAW_PATH'
# and 'DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_GT_PATH' to determine the tag to find within the Zarr
_C.DATA.VAL.INPUT_ZARR_MULTIPLE_DATA = False
# Paths to the raw and gt within the Zarr file. Only used when 'DATA.VAL.INPUT_ZARR_MULTIPLE_DATA' is True.
# E.g. 'volumes.raw' for raw and 'volumes.labels.neuron_ids' for GT path.
_C.DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_RAW_PATH = ""
_C.DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_GT_PATH = ""
# For synapse detection. The information must be stored as CREMI dataset (https://cremi.org/data/)
# Path within the file where the ``ids`` are stored. Reference in CREMI: ``annotations/ids``
_C.DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_ID_PATH = "annotations.ids"
# Path within the file where the ``types`` are stored (not used). Reference in CREMI: ``annotations/types``
# _C.DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_TYPES_PATH = "annotations.types"
# Path within the file where the ``partners`` are stored. Reference in CREMI: ``annotations/partners``
_C.DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_PARTNERS_PATH = "annotations.presynaptic_site.partners"
# Path within the file where the ``locations`` are stored. Reference in CREMI: ``annotations/locations``
_C.DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_LOCATIONS_PATH = "annotations.locations"
# Path within the file where the ``resolution`` is stored. Reference in CREMI: ``["volumes/raw"].attrs["offset"]``
_C.DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_RESOLUTION_PATH = 'volumes.raw'
# File to load/save data prepared with the appropiate channels in a instance segmentation problem.
# E.g. _C.PROBLEM.TYPE ='INSTANCE_SEG' and _C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS != 'B'
_C.DATA.VAL.INSTANCE_CHANNELS_MASK_DIR = os.path.join(
"user_data", "val", "y_" + "".join(_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS)
)
# Path to load/save detection masks prepared.
_C.DATA.VAL.DETECTION_MASK_DIR = os.path.join("user_data", "val", "y_detection_masks")
# Path to load/save SSL target prepared.
_C.DATA.VAL.SSL_SOURCE_DIR = os.path.join("user_data", "val", "x_ssl_source")
# Percentage of overlap in (y,x)/(z,y,x) when cropping validation. Set to 0 to calculate the minimun overlap.
# The values must be floats between range [0, 1). It needs to be a 2D tuple when using _C.PROBLEM.NDIM='2D' and
# 3D tuple when using _C.PROBLEM.NDIM='3D'. This is only used when the validation is loaded from disk, and thus,
# not extracted from training.
_C.DATA.VAL.OVERLAP = (0, 0)
# Padding to be done in (y,x)/(z,y,x) when cropping validation data. Useful to avoid patch 'border effect'. This
# is only used when the validation is loaded from disk, and thus, not extracted from training.
_C.DATA.VAL.PADDING = (0, 0)
# Not used yet.
_C.DATA.VAL.RESOLUTION = (-1,)
# Order of the axes of the image when using Zarr/H5 images in validation data.
_C.DATA.VAL.INPUT_IMG_AXES_ORDER = "TZCYX"
# Order of the axes of the mask when using Zarr/H5 images in validation data.
_C.DATA.VAL.INPUT_MASK_AXES_ORDER = "TZCYX"
# Remove validation images by the conditions based on their properties. When using Zarr each patch within the Zarr will be processed and will
# not depend on 'DATA.FILTER_BY_IMAGE' variable
# The three variables, DATA.VAL.FILTER_SAMPLES.PROPS, DATA.VAL.FILTER_SAMPLES.VALUES and DATA.VAL.FILTER_SAMPLES.SIGNS will compose a list of
# conditions to remove the images. They are list of list of conditions. For instance, the conditions can be like this: [['A'], ['B','C']]. Then,
# if the image satisfies the first list of conditions, only 'A' in this first case (from ['A'] list), or satisfy 'B' and 'C' (from ['B','C'] list)
# it will be removed from the image. In each sublist all the conditions must be satisfied. Available properties are: ['foreground', 'mean', 'min', 'max',
# 'target_mean', 'target_min', 'target_max', 'diff', 'diff_by_min_max_ratio', 'diff_by_target_min_max_ratio'].
#
# Each property descrition:
# * 'foreground' is defined as the percentage of pixels/voxels corresponding to the foreground mask. This option is only valid for
# SEMANTIC_SEG, INSTANCE_SEG and DETECTION.
# * 'mean' is defined as the mean intensity value of the raw image inputs.
# * 'min' is defined as the min intensity value of the raw image inputs.
# * 'max' is defined as the max intensity value of the raw image inputs.
# * 'diff' is defined as the difference between ground truth and raw images. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'diff_by_min_max_ratio' is defined as the difference between ground truth and raw images multiplied by the ratio between raw image max and min. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'target_mean' is defined as the mean intensity value of the raw image targets. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'target_min' is defined as the min intensity value of the raw image targets. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'target_max' is defined as the max intensity value of the raw image targets. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'diff_by_target_min_max_ratio' is defined as the difference between ground truth and raw images multiplied by the ratio between ground truth image max and min. Available for all workflows but SELF_SUPERVISED and DENOISING.
#
# A full example of this filtering:
# If you want to remove those samples that have less than 0.00001 and a mean average more than 100 (you need to know image data type) you should
# declare the above three variables as follows:
# _C.DATA.VAL.FILTER_SAMPLES.PROPS = [['foreground','mean']]
# _C.DATA.VAL.FILTER_SAMPLES.VALUES = [[0.00001, 100]]
# _C.DATA.VAL.FILTER_SAMPLES.SIGNS = [['lt', 'gt']]
# You can also concatenate more restrictions and they will be applied in order. For instance, if you want to filter those
# samples with a max value more than 1000, and do that before the condition described above, you can define the
# variables this way:
# _C.DATA.VAL.FILTER_SAMPLES.PROPS = [['max'], ['foreground','mean']]
# _C.DATA.VAL.FILTER_SAMPLES.VALUES = [[1000], [0.00001, 100]]
# _C.DATA.VAL.FILTER_SAMPLES.SIGNS = [['gt'], ['lt', 'gt']]
# This way, the images will be removed by 'max' and then by 'foreground' and 'mean'
_C.DATA.VAL.FILTER_SAMPLES = CN()
# Whether to enable or not the filtering by properties
_C.DATA.VAL.FILTER_SAMPLES.ENABLE = False
# List of lists of properties to apply a filter. Available properties are: ['foreground', 'mean', 'min', 'max',
# 'target_mean', 'target_min', 'target_max', 'diff', 'diff_by_min_max_ratio', 'diff_by_target_min_max_ratio']
_C.DATA.VAL.FILTER_SAMPLES.PROPS = []
# List of ints/float that represent the values of the properties listed in 'DATA.VAL.FILTER_SAMPLES.PROPS'
# that the images need to satisfy to not be dropped.
_C.DATA.VAL.FILTER_SAMPLES.VALUES = []
# List of list of signs to do the comparison. Options: ['gt', 'ge', 'lt', 'le'] that corresponds to "greather than", e.g. ">",
# "greather equal", e.g. ">=", "less than", e.g. "<", and "less equal" e.g. "<=" comparisons.
_C.DATA.VAL.FILTER_SAMPLES.SIGNS = []
# Whether to normalize the samples before comparison
_C.DATA.VAL.FILTER_SAMPLES.NORM_BEFORE = False
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3.4 Test data options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.DATA.TEST = CN()
# Whether to check if the data mask contains correct values, e.g. same classes as defined
_C.DATA.TEST.CHECK_DATA = True
_C.DATA.TEST.IN_MEMORY = False
# Whether to load ground truth (GT)
_C.DATA.TEST.LOAD_GT = False
# Whether to use validation data as test instead of trying to load test from _C.DATA.TEST.PATH and
# _C.DATA.TEST.GT_PATH. _C.DATA.VAL.CROSS_VAL needs to be True.
_C.DATA.TEST.USE_VAL_AS_TEST = False
# Path to load the test data from. Not used when _C.DATA.TEST.USE_VAL_AS_TEST == True
_C.DATA.TEST.PATH = os.path.join("user_data", "test", "x")
# Path to load the test data masks from. Not used when _C.DATA.TEST.USE_VAL_AS_TEST == True
_C.DATA.TEST.GT_PATH = os.path.join("user_data", "test", "y")
# File to load/save data prepared with the appropiate channels in a instance segmentation problem.
# E.g. _C.PROBLEM.TYPE ='INSTANCE_SEG' and _C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS != 'B'
_C.DATA.TEST.INSTANCE_CHANNELS_MASK_DIR = os.path.join(
"user_data", "test", "y_" + "".join(_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS)
)
# Path to load/save detection masks prepared.
_C.DATA.TEST.DETECTION_MASK_DIR = os.path.join("user_data", "test", "y_detection_masks")
# Path to load/save SSL target prepared.
_C.DATA.TEST.SSL_SOURCE_DIR = os.path.join("user_data", "test", "x_ssl_source")
# Percentage of overlap in (y,x)/(z,y,x) when cropping validation. Set to 0 to calculate the minimun overlap.
# The values must be floats between range [0, 1). It needs to be a 2D tuple when using _C.PROBLEM.NDIM='2D' and
# 3D tuple when using _C.PROBLEM.NDIM='3D'
_C.DATA.TEST.OVERLAP = (0, 0)
# Padding to be done in (y,x)/(z,y,xz) when reconstructing test data. Useful to avoid patch 'border effect'
_C.DATA.TEST.PADDING = (0, 0)
# Whether to use median values to fill padded pixels or zeros
_C.DATA.TEST.MEDIAN_PADDING = False
# Directory where binary masks to apply to resulting images should be. Used when _C.TEST.POST_PROCESSING.APPLY_MASK == True
_C.DATA.TEST.BINARY_MASKS = os.path.join("user_data", "test", "bin_mask")
# Test data resolution. Need to be provided in (z,y,x) order. Only applies when _C.PROBLEM.TYPE = 'DETECTION' now.
_C.DATA.TEST.RESOLUTION = (-1,)
# Order of the axes of the image when using Zarr/H5 images in test data.
_C.DATA.TEST.INPUT_IMG_AXES_ORDER = "TZCYX"
# Order of the axes of the mask when using Zarr/H5 images in test data.
_C.DATA.TEST.INPUT_MASK_AXES_ORDER = "TZCYX"
# Whether your input Zarr contains the raw images and labels together or not. Use 'DATA.TEST.INPUT_ZARR_MULTIPLE_DATA_RAW_PATH'
# and 'DATA.TEST.INPUT_ZARR_MULTIPLE_DATA_GT_PATH' to determine the tag to find within the Zarr
_C.DATA.TEST.INPUT_ZARR_MULTIPLE_DATA = False
# Paths to the raw and gt within the Zarr file. Only used when 'DATA.TEST.INPUT_ZARR_MULTIPLE_DATA' is True.
# E.g. 'volumes.raw' for raw and 'volumes.labels.neuron_ids' for GT path.
_C.DATA.TEST.INPUT_ZARR_MULTIPLE_DATA_RAW_PATH = ""
_C.DATA.TEST.INPUT_ZARR_MULTIPLE_DATA_GT_PATH = ""
# For synapse detection. The information must be stored as CREMI dataset (https://cremi.org/data/)
# Path within the file where the ``ids`` are stored. Reference in CREMI: ``annotations/ids``
_C.DATA.TEST.INPUT_ZARR_MULTIPLE_DATA_ID_PATH = "annotations.ids"
# Path within the file where the ``types`` are stored (not used). Reference in CREMI: ``annotations/types``
# _C.DATA.TEST.INPUT_ZARR_MULTIPLE_DATA_TYPES_PATH = "annotations.types"
# Path within the file where the ``partners`` are stored. Reference in CREMI: ``annotations/partners``
_C.DATA.TEST.INPUT_ZARR_MULTIPLE_DATA_PARTNERS_PATH = "annotations.presynaptic_site.partners"
# Path within the file where the ``locations`` are stored. Reference in CREMI: ``annotations/locations``
_C.DATA.TEST.INPUT_ZARR_MULTIPLE_DATA_LOCATIONS_PATH = "annotations.locations"
# Path within the file where the ``resolution`` is stored. Reference in CREMI: ``["volumes/raw"].attrs["offset"]``
_C.DATA.TEST.INPUT_ZARR_MULTIPLE_DATA_RESOLUTION_PATH = 'volumes.raw'
# Remove test images by the conditions based on their properties. When using Zarr each patch within the Zarr will be processed and will
# not depend on 'DATA.FILTER_BY_IMAGE' variable
# The three variables, DATA.TEST.FILTER_SAMPLES.PROPS, DATA.TEST.FILTER_SAMPLES.VALUES and DATA.TEST.FILTER_SAMPLES.SIGNS will compose a
# list of conditions to remove the images. They are list of list of conditions. For instance, the conditions can be like this: [['A'], ['B','C']].
# Then, if the image satisfies the first list of conditions, only 'A' in this first case (from ['A'] list), or satisfy 'B' and 'C' (from ['B','C'] list)
# it will be removed from the image. In each sublist all the conditions must be satisfied. Available properties are: ['foreground', 'mean', 'min', 'max',
# 'target_mean', 'target_min', 'target_max', 'diff', 'diff_by_min_max_ratio', 'diff_by_target_min_max_ratio'].
#
# Each property descrition:
# * 'foreground' is defined as the percentage of pixels/voxels corresponding to the foreground mask. This option is only valid for
# SEMANTIC_SEG, INSTANCE_SEG and DETECTION.
# * 'mean' is defined as the mean intensity value of the raw image inputs.
# * 'min' is defined as the min intensity value of the raw image inputs.
# * 'max' is defined as the max intensity value of the raw image inputs.
# * 'diff' is defined as the difference between ground truth and raw images. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'diff_by_min_max_ratio' is defined as the difference between ground truth and raw images multiplied by the ratio between raw image max and min. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'target_mean' is defined as the mean intensity value of the raw image targets. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'target_min' is defined as the min intensity value of the raw image targets. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'target_max' is defined as the max intensity value of the raw image targets. Available for all workflows but SELF_SUPERVISED and DENOISING.
# * 'diff_by_target_min_max_ratio' is defined as the difference between ground truth and raw images multiplied by the ratio between ground truth image max and min. Available for all workflows but SELF_SUPERVISED and DENOISING.
#
#
# A full example of this filtering:
# If you want to remove those samples that have less than 0.00001 and a mean average more than 100 (you need to know image data type) you should
# declare the above three variables as follows:
# _C.DATA.TEST.FILTER_SAMPLES.PROPS = [['foreground','mean']]
# _C.DATA.TEST.FILTER_SAMPLES.VALUES = [[0.00001, 100]]
# _C.DATA.TEST.FILTER_SAMPLES.SIGNS = [['lt', 'gt']]
# You can also concatenate more restrictions and they will be applied in order. For instance, if you want to filter those
# samples with a max value more than 1000, and do that before the condition described above, you can define the
# variables this way:
# _C.DATA.TEST.FILTER_SAMPLES.PROPS = [['max'], ['foreground','mean']]
# _C.DATA.TEST.FILTER_SAMPLES.VALUES = [[1000], [0.00001, 100]]
# _C.DATA.TEST.FILTER_SAMPLES.SIGNS = [['gt'], ['lt', 'gt']]
# This way, the images will be removed by 'max' and then by 'foreground' and 'mean'
_C.DATA.TEST.FILTER_SAMPLES = CN()
# Whether to enable or not the filtering by properties
_C.DATA.TEST.FILTER_SAMPLES.ENABLE = False
# List of lists of properties to apply a filter. Available properties are: ['foreground', 'mean', 'min', 'max',
# 'target_mean', 'target_min', 'target_max', 'diff', 'diff_by_min_max_ratio', 'diff_by_target_min_max_ratio']
_C.DATA.TEST.FILTER_SAMPLES.PROPS = []
# List of ints/float that represent the values of the properties listed in 'DATA.TEST.FILTER_SAMPLES.PROPS'
# that the images need to satisfy to not be dropped.
_C.DATA.TEST.FILTER_SAMPLES.VALUES = []
# List of list of signs to do the comparison. Options: ['gt', 'ge', 'lt', 'le'] that corresponds to "greather than", e.g. ">",
# "greather equal", e.g. ">=", "less than", e.g. "<", and "less equal" e.g. "<=" comparisons.
_C.DATA.TEST.FILTER_SAMPLES.SIGNS = []
# Whether to normalize the samples before comparison
_C.DATA.TEST.FILTER_SAMPLES.NORM_BEFORE = False
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3.5 Pre-processing data options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Same preprocessing will be applied to all selected datasets
_C.DATA.PREPROCESS = CN()
# Apply preprocessing to training dataset
_C.DATA.PREPROCESS.TRAIN = False
# Apply preprocessing to validation dataset
_C.DATA.PREPROCESS.VAL = False
# Apply preprocessing to testing dataset
_C.DATA.PREPROCESS.TEST = False
# Resize datasets
_C.DATA.PREPROCESS.RESIZE = CN()
_C.DATA.PREPROCESS.RESIZE.ENABLE = False
# Desired resize size. when using 3D data, size must be also in 3D (ex. (512,512,512))
_C.DATA.PREPROCESS.RESIZE.OUTPUT_SHAPE = (512, 512)
# interpolation order: {0: Nearest-neighbor, 1: Bi-linear (default), 2: Bi-quadratic, 3: Bi-cubic, 4: Bi-quartic, 5: Bi-quintic}
_C.DATA.PREPROCESS.RESIZE.ORDER = 1
# Points outside the boundaries of the input are filled according to the given mode: {'constant', 'edge', 'symmetric', 'reflect', 'wrap'}
_C.DATA.PREPROCESS.RESIZE.MODE = "reflect"
# Used in conjunction with mode 'constant', the value outside the image boundaries.
_C.DATA.PREPROCESS.RESIZE.CVAL = 0.0
# Whether to clip the output to the range of values of the input image.
_C.DATA.PREPROCESS.RESIZE.CLIP = True
# Whether to keep the original range of values.
_C.DATA.PREPROCESS.RESIZE.PRESERVE_RANGE = True
# Whether to apply a Gaussian filter to smooth the image prior to downsampling.
_C.DATA.PREPROCESS.RESIZE.ANTI_ALIASING = False
# Zoom datasets.
_C.DATA.PREPROCESS.ZOOM = CN()
_C.DATA.PREPROCESS.ZOOM.ENABLE = False
# WARNING: Only implemented for _C.TEST.BY_CHUNKS = True. It will change the zoom of each patch individually.
# This is useful when the input image has a different resolution than the one used in the training. The value
# is the zoom factor to be applied to each patch using scipy.ndimage.zoom.
# "E.g. [1,2,1,3,3] that needs to match _C.DATA.TEST.INPUT_IMG_AXES_ORDER axes"
_C.DATA.PREPROCESS.ZOOM.ZOOM_FACTOR = [1, 1, 1, 1, 1]
# Gaussian blur
_C.DATA.PREPROCESS.GAUSSIAN_BLUR = CN()
_C.DATA.PREPROCESS.GAUSSIAN_BLUR.ENABLE = False
# Standard deviation for Gaussian kernel.
_C.DATA.PREPROCESS.GAUSSIAN_BLUR.SIGMA = 1
# The mode parameter determines how the array borders are handled: {'reflect', 'constant', 'nearest', 'mirror', 'wrap'} 'constant' value = 0
_C.DATA.PREPROCESS.GAUSSIAN_BLUR.MODE = "nearest"
# If None, the image is assumed to be a grayscale (single channel) image.
# Otherwise, this parameter indicates which axis of the array corresponds to channels.
_C.DATA.PREPROCESS.GAUSSIAN_BLUR.CHANNEL_AXIS = None
# Median blur
_C.DATA.PREPROCESS.MEDIAN_BLUR = CN()
_C.DATA.PREPROCESS.MEDIAN_BLUR.ENABLE = False
# Desired kernel size (including channels). When using 3D data, size must be also in 3D (ex. (3,7,7,1) for (z,y,x,c))
_C.DATA.PREPROCESS.MEDIAN_BLUR.KERNEL_SIZE = (3,3,1)
# Histogram matching. More info at: https://en.wikipedia.org/wiki/Histogram_matching
_C.DATA.PREPROCESS.MATCH_HISTOGRAM = CN()
_C.DATA.PREPROCESS.MATCH_HISTOGRAM.ENABLE = False
# the path of the reference images, from which the reference histogram will be extracted
_C.DATA.PREPROCESS.MATCH_HISTOGRAM.REFERENCE_PATH = os.path.join("user_data", "test", "x")
# Contrast Limited Adaptive Histogram Equalization. More info at: https://en.wikipedia.org/wiki/Adaptive_histogram_equalization#Contrast_Limited_AHE
_C.DATA.PREPROCESS.CLAHE = CN()
_C.DATA.PREPROCESS.CLAHE.ENABLE = False
# Defines the shape of contextual regions used in the algorithm.
# By default, kernel_size is 1/8 of image height by 1/8 of its width.
_C.DATA.PREPROCESS.CLAHE.KERNEL_SIZE = None
# Clipping limit, normalized between 0 and 1 (higher values give more contrast).
_C.DATA.PREPROCESS.CLAHE.CLIP_LIMIT = 0.01
# Canny or edge detection (only 2D - grayscale or RGB)
_C.DATA.PREPROCESS.CANNY = CN()
_C.DATA.PREPROCESS.CANNY.ENABLE = False
# Lower bound for hysteresis thresholding (linking edges). If None, low_threshold is set to 10% of dtype's max.
_C.DATA.PREPROCESS.CANNY.LOW_THRESHOLD = None
# Upper bound for hysteresis thresholding (linking edges). If None, high_threshold is set to 20% of dtype's max.
_C.DATA.PREPROCESS.CANNY.HIGH_THRESHOLD = None
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 4. Data augmentation (DA)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.AUGMENTOR = CN()
# Flag to activate DA
_C.AUGMENTOR.ENABLE = False
# Probability of each transformation
_C.AUGMENTOR.DA_PROB = 0.5
# Create samples of the DA made. Useful to check the output images made.
_C.AUGMENTOR.AUG_SAMPLES = True
# Draw a grid in the augenation samples generated. Used when _C.AUGMENTOR.AUG_SAMPLES=True
_C.AUGMENTOR.DRAW_GRID = True
# Number of samples to create
_C.AUGMENTOR.AUG_NUM_SAMPLES = 10
# Flag to shuffle the training data on every epoch
_C.AUGMENTOR.SHUFFLE_TRAIN_DATA_EACH_EPOCH = True
# Flag to shuffle the validation data on every epoch
_C.AUGMENTOR.SHUFFLE_VAL_DATA_EACH_EPOCH = False
# Rotation of 90º to the subvolumes
_C.AUGMENTOR.ROT90 = False
# Random rotation between a defined range
_C.AUGMENTOR.RANDOM_ROT = False
# Range of random rotations
_C.AUGMENTOR.RANDOM_ROT_RANGE = (-180, 180)
# Apply shear to images
_C.AUGMENTOR.SHEAR = False
# Shear range. Expected value range is around [-360, 360], with reasonable values being in the range of [-45, 45].
_C.AUGMENTOR.SHEAR_RANGE = (-20, 20)
# Apply zoom to images
_C.AUGMENTOR.ZOOM = False
# Zoom range. Scaling factor to use, where 1.0 denotes “no change” and 0.5 is zoomed out to 50 percent of the original size.
_C.AUGMENTOR.ZOOM_RANGE = (0.8, 1.2)
# Whether to apply or not zoom in Z axis (for 3D volumes).
_C.AUGMENTOR.ZOOM_IN_Z = False
# Apply shift
_C.AUGMENTOR.SHIFT = False
# Shift range. Translation as a fraction of the image height/width (x-translation, y-translation), where 0 denotes
# “no change” and 0.5 denotes “half of the axis size”.
_C.AUGMENTOR.SHIFT_RANGE = (0.1, 0.2)
# How to fill up the new values created with affine transformations (rotations, shear, shift and zoom).
# Only keep modes common to skimage & scipy: 'constant', 'reflect', 'wrap' and 'symmetric
# Dropped 'edge'/'nearest' for simplicity
_C.AUGMENTOR.AFFINE_MODE = "reflect"
# Make vertical flips
_C.AUGMENTOR.VFLIP = False
# Make horizontal flips
_C.AUGMENTOR.HFLIP = False
# Make z-axis flips
_C.AUGMENTOR.ZFLIP = False
# Elastic transformations
_C.AUGMENTOR.ELASTIC = False
# Strength of the distortion field. Higher values mean that pixels are moved further with respect to the distortion
# field's direction. Set this to around 10 times the value of sigma for visible effects.
_C.AUGMENTOR.E_ALPHA = (12, 16)
# Standard deviation of the gaussian kernel used to smooth the distortion fields. Higher values (for 128x128 images
# around 5.0) lead to more water-like effects, while lower values (for 128x128 images around 1.0 and lower) lead to
# more noisy, pixelated images. Set this to around 1/10th of alpha for visible effects.
_C.AUGMENTOR.E_SIGMA = 4
# Parameter that defines the handling of newly created pixels with the elastic transformation
_C.AUGMENTOR.E_MODE = "constant"
# Gaussian blur
_C.AUGMENTOR.G_BLUR = False
# Standard deviation of the gaussian kernel. Values in the range 0.0 (no blur) to 3.0 (strong blur) are common.
_C.AUGMENTOR.G_SIGMA = (1.0, 2.0)
# To blur an image by computing median values over neighbourhoods
_C.AUGMENTOR.MEDIAN_BLUR = False
# Median blur kernel size
_C.AUGMENTOR.MB_KERNEL = (3, 7)
# Blur images in a way that fakes camera or object movements
_C.AUGMENTOR.MOTION_BLUR = False
# Kernel size to use in motion blur
_C.AUGMENTOR.MOTB_K_RANGE = (8, 12)
# Gamma contrast
_C.AUGMENTOR.GAMMA_CONTRAST = False
# Exponent for the contrast adjustment. Higher values darken the image
_C.AUGMENTOR.GC_GAMMA = (1.25, 1.75)
# To apply brightness changes to images
_C.AUGMENTOR.BRIGHTNESS = False
# Strength of the brightness range.
_C.AUGMENTOR.BRIGHTNESS_FACTOR = (-0.1, 0.1)
# To apply contrast changes to images
_C.AUGMENTOR.CONTRAST = False
# Strength of the contrast change range.
_C.AUGMENTOR.CONTRAST_FACTOR = (-0.1, 0.1)
# Set a certain fraction of pixels in images to zero (not get confused with the dropout concept of neural networks)
_C.AUGMENTOR.DROPOUT = False
# Range to take the probability to drop a pixel
_C.AUGMENTOR.DROP_RANGE = (0, 0.2)
# To fill one or more rectangular areas in an image using a fill mode
_C.AUGMENTOR.CUTOUT = False
# Range of number of areas to fill the image with. Reasonable values between range [0,4]
_C.AUGMENTOR.COUT_NB_ITERATIONS = (1, 3)
# Size of the areas in % of the corresponding image size
_C.AUGMENTOR.COUT_SIZE = (0.05, 0.3)
# Value to fill the area of cutout
_C.AUGMENTOR.COUT_CVAL = 0.0
# Apply cutout to the segmentation mask
_C.AUGMENTOR.COUT_APPLY_TO_MASK = False
# To apply cutblur operation
_C.AUGMENTOR.CUTBLUR = False
# Size of the region to apply cutblur
_C.AUGMENTOR.CBLUR_SIZE = (0.2, 0.4)
# Range of the downsampling to be made in cutblur
_C.AUGMENTOR.CBLUR_DOWN_RANGE = (2, 8)
# Whether to apply cut-and-paste just LR into HR image. If False, HR to LR will be applied also (see Figure 1
# of the paper https://arxiv.org/pdf/2004.00448.pdf)
_C.AUGMENTOR.CBLUR_INSIDE = True
# Apply cutmix operation
_C.AUGMENTOR.CUTMIX = False
# Size of the region to apply cutmix
_C.AUGMENTOR.CMIX_SIZE = (0.2, 0.4)
# Apply noise to a region of the image
_C.AUGMENTOR.CUTNOISE = False
# Range to choose a value that will represent the % of the maximum value of the image that will be used as the std
# of the Gaussian Noise distribution
_C.AUGMENTOR.CNOISE_SCALE = (0.05, 0.1)
# Number of areas to fill with noise
_C.AUGMENTOR.CNOISE_NB_ITERATIONS = (1, 3)
# Size of the regions
_C.AUGMENTOR.CNOISE_SIZE = (0.2, 0.4)
# Add miss-aligment augmentation
_C.AUGMENTOR.MISALIGNMENT = False
# Maximum pixel displacement in 'xy'-plane for misalignment
_C.AUGMENTOR.MS_DISPLACEMENT = 16
# Ratio of rotation-based mis-alignment
_C.AUGMENTOR.MS_ROTATE_RATIO = 0.5
# Augment the image by creating a black line in a random position
_C.AUGMENTOR.MISSING_SECTIONS = False
# Probability of adding a missing section in each channel
_C.AUGMENTOR.MISSP_CHANNEL_PB = 0.5
# Iterations to dilate the missing line with
_C.AUGMENTOR.MISSP_ITERATIONS = (10, 30)
# Convert images in grasycale gradually based on '_C.AUGMENTOR.GRAY_RANGE'
_C.AUGMENTOR.GRAYSCALE = False
# Shuffle channels of the images
_C.AUGMENTOR.CHANNEL_SHUFFLE = False
# Apply gridmask to the image. Original paper: https://arxiv.org/pdf/2001.04086v1.pdf
_C.AUGMENTOR.GRIDMASK = False
# Determines the keep ratio of an input image
_C.AUGMENTOR.GRID_RATIO = 0.6
# Range to choose a d value
_C.AUGMENTOR.GRID_D_RANGE = (0.4, 1)
# Rotation of the mask in GridMask. Needs to be between [0,1] where 1 is 360 degrees.
_C.AUGMENTOR.GRID_ROTATE = 1.0
# Whether to invert the mask
_C.AUGMENTOR.GRID_INVERT = False
# Add Gaussian noise
_C.AUGMENTOR.GAUSSIAN_NOISE = False
_C.AUGMENTOR.GAUSSIAN_NOISE_MEAN = 0.0
_C.AUGMENTOR.GAUSSIAN_NOISE_VAR = 0.05
_C.AUGMENTOR.GAUSSIAN_NOISE_USE_INPUT_IMG_MEAN_AND_VAR = False
# Add Poisson noise
_C.AUGMENTOR.POISSON_NOISE = False
# Add salt (replaces random pixels with 1)
_C.AUGMENTOR.SALT = False
_C.AUGMENTOR.SALT_AMOUNT = 0.05
# Add pepper (replaces random pixels with 0 (for unsigned images) or -1 (for signed images))
_C.AUGMENTOR.PEPPER = False
_C.AUGMENTOR.PEPPER_AMOUNT = 0.05
# Whether to add Poisson noise
_C.AUGMENTOR.SALT_AND_PEPPER = False
_C.AUGMENTOR.SALT_AND_PEPPER_AMOUNT = 0.05
_C.AUGMENTOR.SALT_AND_PEPPER_PROP = 0.5
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 5. Model definition
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.MODEL = CN()
# Whether to define manually the model ('biapy'), load a pretrained one from BioImage Model Zoo ('bmz') or use one
# available in TorchVision ('torchvision').
# Options: ["biapy", "bmz", "torchvision"]
_C.MODEL.SOURCE = "biapy"
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 5.1 BiaPy backend models options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Architecture of the network. Possible values are:
# * Semantic segmentation: 'unet', 'resunet', 'resunet++', 'attention_unet', 'multiresunet', 'seunet', 'resunet_se', 'unetr', 'unext_v1', 'unext_v2',
# 'hrnet' and 'stunet'
# * Instance segmentation: 'unet', 'resunet', 'resunet++', 'attention_unet', 'multiresunet', 'seunet', 'resunet_se', 'unetr', 'unext_v1', 'unext_v2',
# 'hrnet' and 'stunet'
# * Detection: 'unet', 'resunet', 'resunet++', 'attention_unet', 'multiresunet', 'seunet', 'resunet_se', 'unetr', 'unext_v1', 'unext_v2', 'hrnet' and
# 'stunet'
# * Denoising: 'unet', 'resunet', 'resunet++', 'attention_unet', 'seunet', 'resunet_se', 'unext_v1', 'unext_v2', 'hrnet' and 'stunet'
# * Super-resolution: 'edsr', 'rcan', 'dfcan', 'wdsr', 'unet', 'resunet', 'resunet++', 'seunet', 'resunet_se', 'attention_unet', 'multiresunet', 'unext_v1'
# and 'unext_v2'
# * Self-supervision: 'unet', 'resunet', 'resunet++', 'attention_unet', 'multiresunet', 'seunet', 'resunet_se', 'unetr', 'edsr', 'rcan', 'dfcan', 'wdsr', 'vit',
# 'mae', 'unext_v1', 'unext_v2', 'hrnet' and 'stunet'
# * Classification: 'simple_cnn', 'vit' and 'efficientnet_b[0-7]' (only 2D)
# * Image to image: 'edsr', 'rcan', 'dfcan', 'wdsr', 'unet', 'resunet', 'resunet++', 'seunet', 'resunet_se', 'attention_unet', 'unetr', 'multiresunet', 'unext_v1',
# 'unext_v2', 'hrnet' and 'stunet'
_C.MODEL.ARCHITECTURE = "unet"
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 5.1.1 U-Net-like architectures options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Number of feature maps on each level of the network. Works with 'unet', 'resunet', 'resunet++', 'attention_unet', 'multiresunet', 'seunet', 'resunet_se',
# 'unext_v1', 'unext_v2' architectures.
_C.MODEL.FEATURE_MAPS = [16, 32, 64, 128, 256]
# Values to make the dropout with. Set to 0 to prevent dropout. When using it with 'ViT' or 'unetr' a list with just one number must be provided. Works with
# 'unet', 'resunet', 'resunet++', 'attention_unet', 'multiresunet', 'seunet', 'resunet_se' and 'unetr' architectures.
_C.MODEL.DROPOUT_VALUES = [0.0, 0.0, 0.0, 0.0, 0.0]
# Normalization layer (one of 'bn', 'sync_bn' 'in', 'ln', 'gn' or 'none'). Works with 'unet', 'resunet', 'resunet++', 'attention_unet', 'multiresunet', 'seunet',
# 'resunet_se', 'unetr', 'hrnet' architectures.
_C.MODEL.NORMALIZATION = "in"
# to set the kernel size for the convolutional layers. Works with 'unet', 'resunet', 'resunet++', 'attention_unet', 'multiresunet', 'seunet', 'resunet_se'
# and 'unetr' architectures.
_C.MODEL.KERNEL_SIZE = 3
# Upsampling layer to use in the model. Options: ["upsampling", "convtranspose"]. Works with 'unet', 'resunet', 'resunet++', 'attention_unet', 'multiresunet',
# 'seunet' and 'resunet_se' architectures.
_C.MODEL.UPSAMPLE_LAYER = "convtranspose"
# Activation function to use along the model (not in the final layer). Options: 'relu', 'tanh', 'leaky_relu', 'elu', 'gelu', 'silu', 'sigmoid', 'softmax', 'linear',
# 'softplus' and 'none'. Works with 'unet', 'resunet', 'resunet++', 'attention_unet', 'multiresunet', 'seunet', 'resunet_se', 'unetr' and 'hrnet' architectures.
_C.MODEL.ACTIVATION = "elu"
# Downsampling to be made in Z. This value will be the third integer of the MaxPooling operation. When facing anysotropic datasets set it to get better performance.
# Works with 'unet', 'resunet', 'resunet++', 'attention_unet', 'multiresunet', 'seunet', 'resunet_se', 'unext_v1' and 'unext_v2' architectures.
_C.MODEL.Z_DOWN = [0, 0, 0, 0]
# Downsampling to be made in XY. This value will be the first and second integer of the MaxPooling operation. When facing anysotropic datasets set it to get better
# performance. Works with 'unet', 'resunet', 'resunet++', 'attention_unet', 'multiresunet', 'seunet', 'resunet_se', 'unext_v1' and 'unext_v2' architectures.
_C.MODEL.YX_DOWN = [0, 0, 0, 0]
# For each level of the model (U-Net levels), set to true or false if the dimensions of the feature maps are isotropic. Works with 'unet', 'resunet', 'resunet++',
# 'attention_unet', 'multiresunet', 'seunet', 'resunet_se', 'unext_v1' and 'unext_v2' architectures.
_C.MODEL.ISOTROPY = [True, True, True, True, True]
# Include extra convolutional layers with larger kernel at the beginning and end of the U-Net-like model. Works with 'unet', 'resunet', 'resunet++', 'attention_unet',
# 'multiresunet', 'seunet' and 'resunet_se' architectures.
_C.MODEL.LARGER_IO = False
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 5.1.1.1 U-NeXT (v1 and v2) architectures options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# "unext_v1" and "unext_v2" architectures variables. These architectures are based on the ConvNeXt architecture (https://arxiv.org/abs/2201.03545) and they
# are adapted to the U-Net structure.
# Number of ConvNeXtBlocks in each level.
_C.MODEL.CONVNEXT_LAYERS = [2, 2, 2, 2, 2] # CONVNEXT_LAYERS
# Maximum Stochastic Depth probability for the U-NeXt model.
_C.MODEL.CONVNEXT_SD_PROB = 0.1
# Layer Scale parameter for the U-NeXt model. Only valid for the "unext_v1" architecture.
_C.MODEL.CONVNEXT_LAYER_SCALE = 1e-6
# Size of the stem kernel in the U-NeXt model.
_C.MODEL.CONVNEXT_STEM_K_SIZE = 2
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 5.1.1.2 UNETR architecture options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Multiple of the transformer encoder layers from of which the skip connection signal is going to be extracted
_C.MODEL.UNETR_VIT_HIDD_MULT = 3
# Number of filters in the first UNETR's layer of the decoder. In each layer the previous number of filters is doubled.
_C.MODEL.UNETR_VIT_NUM_FILTERS = 16
# Specific for SR models based on U-Net architectures. Options are ["pre", "post"]
_C.MODEL.UNET_SR_UPSAMPLE_POSITION = "pre"
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 5.1.2 Transformer-based architectures options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Type of ViT model. Options are "custom", "vit_base_patch16", "vit_large_patch16" and "vit_huge_patch16". On "custom" setting
# the rest of the ViT parameters can be modified as other options will set them automatically.
_C.MODEL.VIT_MODEL = "custom"
# Size of the patches that are extracted from the input image.
_C.MODEL.VIT_TOKEN_SIZE = 16
# Dimension of the embedding space
_C.MODEL.VIT_EMBED_DIM = 768
# Number of transformer encoder layers
_C.MODEL.VIT_NUM_LAYERS = 12
# Number of heads in the multi-head attention layer.
_C.MODEL.VIT_NUM_HEADS = 12
# Size of the dense layers of the final classifier. This value will mutiply 'VIT_EMBED_DIM'
_C.MODEL.VIT_MLP_RATIO = 4.0
# Normalization layer epsion
_C.MODEL.VIT_NORM_EPS = 1e-6
# ViT architecture adapted for self-supervised learning with masked autoencoders (MAE). Original paper: https://arxiv.org/abs/2111.06377
# Dimension of the embedding space for the MAE decoder
_C.MODEL.MAE_DEC_HIDDEN_SIZE = 512
# Number of transformer decoder layers
_C.MODEL.MAE_DEC_NUM_LAYERS = 8
# Number of heads in the multi-head attention layer.
_C.MODEL.MAE_DEC_NUM_HEADS = 16
# Size of the dense layers of the final classifier
_C.MODEL.MAE_DEC_MLP_DIMS = 2048
# Type of the masking strategy. Options: ["grid", "random"]
_C.MODEL.MAE_MASK_TYPE = "grid"
# Percentage of the input image to mask (applied only when MODEL.MAE_MASK_TYPE == "random"). Value between 0 and 1.
_C.MODEL.MAE_MASK_RATIO = 0.5
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 5.1.3 RCAN architecture options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Number of RG modules
_C.MODEL.RCAN_RG_BLOCK_NUM = 10
# Number of RCAB modules in each RG block
_C.MODEL.RCAN_RCAB_BLOCK_NUM = 20
# Filters in the convolutions
_C.MODEL.RCAN_CONV_FILTERS = 16
# Channel reduction ratio for channel attention
_C.MODEL.RCAN_REDUCTION_RATIO = 16
# Whether to maintain or not the upscaling layer.
_C.MODEL.RCAN_UPSCALING_LAYER = True
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 5.1.4 HRNet architecture options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# These parameters can be used as a template for building custom HRNet versions
_C.MODEL.HRNET = CN()
# Whether to use a custom configuration for HRNet or use a predefined one. Options: "W18" (hrnet18), "W32" (hrnet32),
# "W48" (hrnet48), "W64" (hrnet64) or "custom"
_C.MODEL.HRNET.VARIANT = "W48"
# Whether to downsample the input in Z or not
_C.MODEL.HRNET.Z_DOWN = [0, 0, 0]
# Downsampling to be made in XY. This value will be the first and second integer of the MaxPooling operation.
# When facing anysotropic datasets set it to get better performance
_C.MODEL.HRNET.YX_DOWN = [0, 0, 0]
# Type of block to use in HRNet. Options: 'BASIC', 'BOTTLENECK', 'CONVNEXT_V1' and 'CONVNEXT_V2'
_C.MODEL.HRNET.BLOCK_TYPE = 'BASIC'
# Indicate whether to use a custom configuration for HRNet or use a predefined one. Options: "OCR", "ASPP", "PSP", "FCN"
_C.MODEL.HRNET.HEAD_TYPE = "FCN"
# Number of stages in the HRNet. This value will determine the length of the rest of the lists. Only used if MODEL.HRNET.VARIANT = "custom"
_C.MODEL.HRNET.NUM_STAGES = 3
# Number of modules in each stage. Only used if MODEL.HRNET.VARIANT = "custom". A module is a sequence of blocks (see MODEL.HRNET.BLOCK_TYPE)
# that are not connected with the rest of branches. In each stage, after the modules, a fusion is made between all the branches. So, the
# number of modules will determine how many times the fusion is made in each stage.
_C.MODEL.HRNET.NUM_MODULES = [1, 4, 3]
# Number of branches in each stage. Only used if MODEL.HRNET.VARIANT = "custom". The number of branches will determine how many parallel convolutions
# are made in each stage and how many feature maps with different resolutions are generated.
_C.MODEL.HRNET.NUM_BRANCHES = [2, 3, 4]
# Number of blocks in each branch of each stage. Only used if MODEL.HRNET.VARIANT = "custom". A block is a convolutional operation
# (see MODEL.HRNET.BLOCK_TYPE) that is repeated a certain number of times in each branch. The number of blocks will determine the
# depth of the model.
_C.MODEL.HRNET.NUM_BLOCKS = [[4, 4], [4, 4, 4], [4, 4, 4, 4]]
# Number of channels in each block of each branch of each stage. Only used if MODEL.HRNET.VARIANT = "custom". The number of channels
# will determine the width of the model.
_C.MODEL.HRNET.NUM_CHANNELS = [[18, 36], [18, 36, 72], [18, 36, 72, 144]]
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 5.1.5 STUNet architecture options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.MODEL.STUNET = CN()
# Variant of the STUNet model. Options are: 'small', 'base', 'large'
_C.MODEL.STUNET.VARIANT = 'base'
# Whether to use a pretrained version of STUNet on ImageNet
_C.MODEL.STUNET.PRETRAINED = False
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 5.1.6 Checkpoint options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# To load a model (and more items if available) from a given checkpoint. Items that can be loaded are defined in 'MODEL.ITEMS_TO_LOAD_FROM_CHECKPOINT'.
_C.MODEL.LOAD_CHECKPOINT = False
# List of items to load from the checkpoint (if available). Options are:
# * "weights": to load the model weights
# * "norm": to load the normalization used. Unless you know that the checkpoint was trained with the same normalization as the one defined in the config,
# it is recommended to load it from the checkpoint if "weights" is also specified, as the model will expect the input data to be normalized accordingly.
# * "model_arch": to load the model architecture
# * "optimizer": to load the optimizer state dict
# * "epoch": to load the epoch number from which the training will be resumed
#
# Defining it with "weights" and "model_arch" will allow to load the model weights and architecture, but not the
# optimizer state, which is useful when doing inference or fine-tunning. Defining it with all options
# will allow to resume training from a checkpoint.
_C.MODEL.ITEMS_TO_LOAD_FROM_CHECKPOINT = ["weights", "norm", "model_arch"]
# Decide which checkpoint to load from job's dir if PATHS.CHECKPOINT_FILE is ''.
# Options: 'best_on_val' or 'last_on_train'
_C.MODEL.LOAD_CHECKPOINT_EPOCH = "best_on_val"
# Format of the output checkpoint. Options are 'pth' (native PyTorch format) or 'safetensors' (https://github.com/huggingface/safetensors)
_C.MODEL.OUT_CHECKPOINT_FORMAT = "pth"
# To skip loading those layers that do not match in shape with the given checkpoint. If this is set to False a regular load function will be
# done, which will fail if a layer mismatch is found. Only works when 'MODEL.LOAD_MODEL_FROM_CHECKPOINT' is True
_C.MODEL.SKIP_UNMATCHED_LAYERS = False
# Epochs to save a checkpoint of the model apart from the best of the validation. Set it to -1 to not do it.
_C.MODEL.SAVE_CKPT_FREQ = -1
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 5.2 BioImage Model Zoo (BMZ) options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# BMZ model export options
_C.MODEL.BMZ = CN()
# DOI or nickname of the model from BMZ to load. It can not be empty if MODEL.SOURCE = "bmz".
_C.MODEL.BMZ.SOURCE_MODEL_ID = ""
# Module to export the model to BMZ format. It will be activated when 'MODEL.BMZ.EXPORT.ENABLE' is set to True.
_C.MODEL.BMZ.EXPORT = CN()
# Whether to activate or not the exporation of the used model to the BMZ format after train and/or test
_C.MODEL.BMZ.EXPORT.ENABLE = False
# Name of the model to create. It should be something meaningful. Take other models in https://bioimage.io/#/ as reference.
_C.MODEL.BMZ.EXPORT.MODEL_NAME = ""
# Description of the model. It should be something meaningful. Take other models in https://bioimage.io/#/ as reference.
# E.g. "Mitochondria segmentation for electron microscopy"
_C.MODEL.BMZ.EXPORT.DESCRIPTION = ""
# List of authors of the model. Each item must be a dict containing "name" and "githubuser".
# E.g. [{"name": "Daniel", "github_user": "danifranco"}]
_C.MODEL.BMZ.EXPORT.AUTHORS = []
# License of the model.
_C.MODEL.BMZ.EXPORT.LICENSE = "CC-BY-4.0"
# Path to a .md extension file with the documentation of the model. If it is not set so the model documentation will be
# automatically generated with the information provided. If you want to add more information you can use this option.
# E.g. to provide more details of the training procedure, data, etc.
_C.MODEL.BMZ.EXPORT.DOCUMENTATION = ""
# List of tags. Here the type of dataset and the target object should be provided. BiaPy automatically sets the following tags:
# * "biapy": to represent that the model was created with BiaPy.
# * "pytorch": to represent that you are using Pytorch
# * "2d" or "3d": depending on the image dimensions one or the other is selected.
# * workflow tag: depending on the workflow the tag is set. E.g. "semantic-segmentation"
#
# So, what you can set for instance is: ["electron-microscopy", "mitochondria"]
_C.MODEL.BMZ.EXPORT.TAGS = []
# Citations. It must be a list of dictionaries with keys "text" and "doi". E.g.:
# [{"text": "training library", "doi": "10.1038/s41592-025-02699-y"}, {"text": "architecture", "doi": "10.1109/LGRS.2018.2802944"},
# {"text": "data", "doi": "10.48550/arXiv.1812.06024"}]
_C.MODEL.BMZ.EXPORT.CITE = []
# Information of the dataset. It must be a list of just one dict item with keys "name", "doi" and "image_modality". It can have
# also "dataset_id" key but it is optional (must match a dataset in the BioImage Model Zoo). E.g:
# [{
# "name": "CartoCell",
# "doi": "10.1016/j.crmeth.2023.100597",
# "image_modality": "fluorescence microscopy",
# "dataset_id": "biapy/cartocell_cyst_segmentation",
# }]
_C.MODEL.BMZ.EXPORT.DATASET_INFO = [{}]
# Version of the model
_C.MODEL.BMZ.EXPORT.MODEL_VERSION = "0.1.0"
# If you are loading a BMZ model you can enable this option to avoid setting all above variables and instead reuse the same
# information that was present in that model. You need still to set 'MODEL.BMZ.EXPORT.ENABLE' to 'True' and nothing else.
_C.MODEL.BMZ.EXPORT.REUSE_BMZ_CONFIG = False
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 5.2 TorchVision options (limited support)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# BiaPy support using models of Torchvision. However, most of the models were trained in natural images (not biomedical) and most of them
# are for classification. On top of that, some use bounding-box-annotations, which are not supported in BiaPy so only inference/prediction/test
# can only be done. 'MODEL.TORCHVISION_MODEL_NAME' variable can not be empty if MODEL.SOURCE = "torchvision".
# Models available here: https://pytorch.org/vision/stable/models.html
# They can be listed with: "from torchvision.models import list_models; list_models()"
#
# Semantic segmentation (https://pytorch.org/vision/stable/models.html#semantic-segmentation):
# 'deeplabv3_mobilenet_v3_large', 'deeplabv3_resnet101', 'deeplabv3_resnet50', 'fcn_resnet101', 'fcn_resnet50',
# 'lraspp_mobilenet_v3_large'
#
# Object Detection (https://pytorch.org/vision/stable/models.html#object-detection-instance-segmentation-and-person-keypoint-detection)
# 'fasterrcnn_mobilenet_v3_large_320_fpn', 'fasterrcnn_mobilenet_v3_large_fpn', 'fasterrcnn_resnet50_fpn',
# 'fasterrcnn_resnet50_fpn_v2', 'fcos_resnet50_fpn', 'ssd300_vgg16', 'ssdlite320_mobilenet_v3_large',
# 'retinanet_resnet50_fpn', 'retinanet_resnet50_fpn_v2',
#
# Instance Segmentation (https://pytorch.org/vision/stable/models.html#object-detection-instance-segmentation-and-person-keypoint-detection)
# 'maskrcnn_resnet50_fpn', 'maskrcnn_resnet50_fpn_v2'
#
# Image classification (https://pytorch.org/vision/stable/models.html#classification):
# 'alexnet', 'convnext_base', 'convnext_large', 'convnext_small', 'convnext_tiny', 'densenet121', 'densenet161',
# 'densenet169', 'densenet201', 'efficientnet_b0', 'efficientnet_b1', 'efficientnet_b2', 'efficientnet_b3',
# 'efficientnet_b4', 'efficientnet_b5', 'efficientnet_b6', 'efficientnet_b7', 'efficientnet_v2_l', 'efficientnet_v2_m',
# 'efficientnet_v2_s', 'googlenet', 'inception_v3', 'maxvit_t', 'mnasnet0_5', 'mnasnet0_75', 'mnasnet1_0', 'mnasnet1_3',
# 'mobilenet_v2', 'mobilenet_v3_large', 'mobilenet_v3_small', 'quantized_googlenet', 'quantized_inception_v3',
# 'quantized_mobilenet_v2', 'quantized_mobilenet_v3_large', 'quantized_resnet18', 'quantized_resnet50',
# 'quantized_resnext101_32x8d', 'quantized_resnext101_64x4d', 'quantized_shufflenet_v2_x0_5', 'quantized_shufflenet_v2_x1_0',
# 'quantized_shufflenet_v2_x1_5', 'quantized_shufflenet_v2_x2_0', 'regnet_x_16gf', 'regnet_x_1_6gf', 'regnet_x_32gf',
# 'regnet_x_3_2gf', 'regnet_x_400mf', 'regnet_x_800mf', 'regnet_x_8gf', 'regnet_y_128gf', 'regnet_y_16gf', 'regnet_y_1_6gf',
# 'regnet_y_32gf', 'regnet_y_3_2gf', 'regnet_y_400mf', 'regnet_y_800mf', 'regnet_y_8gf', 'resnet101', 'resnet152',
# 'resnet18', 'resnet34', 'resnet50', 'resnext101_32x8d', 'resnext101_64x4d', 'resnext50_32x4d', 'retinanet_resnet50_fpn',
# 'shufflenet_v2_x0_5', 'shufflenet_v2_x1_0', 'shufflenet_v2_x1_5', 'shufflenet_v2_x2_0',
# 'squeezenet1_0', 'squeezenet1_1', 'swin_b', 'swin_s', 'swin_t', 'swin_v2_b', 'swin_v2_s', 'swin_v2_t',
# 'vgg11', 'vgg11_bn', 'vgg13', 'vgg13_bn', 'vgg16', 'vgg16_bn', 'vgg19', 'vgg19_bn', 'vit_b_16', 'vit_b_32',
# 'vit_h_14', 'vit_l_16', 'vit_l_32', 'wide_resnet101_2', 'wide_resnet50_2'
#
# Listed but not supported:
#
# (NOT SUPPORTED) Video classification (https://pytorch.org/vision/stable/models.html#video-classification):
# 'mc3_18', 'mvit_v1_b', 'mvit_v2_s', 'r2plus1d_18', 'r3d_18','swin3d_s', 'swin3d_t', 's3d', 'swin3d_b'
#
# (NOT SUPPORTED) Optical flow (https://pytorch.org/vision/stable/models.html#optical-flow):
# 'raft_large', 'raft_small'
#
# (NOT SUPPORTED) Person Keypoint Detection (https://pytorch.org/vision/stable/models.html#object-detection-instance-segmentation-and-person-keypoint-detection)
# 'keypointrcnn_resnet50_fpn'
#
_C.MODEL.TORCHVISION_MODEL_NAME = ""
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 6. Loss definition options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.LOSS = CN()
# Loss type, different options depending on the workflow. If empty the default loss on each case will be set:
# * Semantic segmentation:
# * "CE" (default): cross entropy. Ref: https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html
# * "DICE": Dice loss. Ref: https://www.kaggle.com/code/bigironsphere/loss-function-library-keras-pytorch
# * "W_CE_DICE": CE and Dice (with a weight term on each one that must sum 1). Ref: https://www.kaggle.com/code/bigironsphere/loss-function-library-keras-pytorch
# * Instance segmentation: automatically set depending on the channels selected (PROBLEM.INSTANCE_SEG.DATA_CHANNELS).
# It can be also set manually with PROBLEM.INSTANCE_SEG.DATA_CHANNELS_LOSSES.
# * Detection: CE always used. Ref: https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html
# * Denoising:
# * "MAE": mean absolute error (MAE or L1 loss). Ref: https://pytorch.org/docs/stable/generated/torch.nn.L1Loss.html#torch.nn.L1Loss
# * "MSE" (default): mean square error (MSE). Ref: https://pytorch.org/docs/stable/generated/torch.nn.MSELoss.html#torch.nn.MSELoss
# * Super-resolution:
# * "MAE" (default): mean absolute error (MAE or L1 loss). Ref: https://pytorch.org/docs/stable/generated/torch.nn.L1Loss.html#torch.nn.L1Loss
# * "MSE": mean square error (MSE). Ref: https://pytorch.org/docs/stable/generated/torch.nn.MSELoss.html#torch.nn.MSELoss
# * "SSIM": structural similarity index measure (SSIM). Ref: https://lightning.ai/docs/torchmetrics/stable/image/structural_similarity.html#torchmetrics.image.StructuralSimilarityIndexMeasure
# * "W_MAE_SSIM": MAE and SSIM (with a weight term on each one that must sum 1).
# * "W_MSE_SSIM": MSE and SSIM (with a weight term on each one that must sum 1).
# * Self-supervision:
# These losses can only be set when PROBLEM.SELF_SUPERVISED.PRETEXT_TASK = "crappify". Otherwise it will be automatically set to MSE when
# PROBLEM.SELF_SUPERVISED.PRETEXT_TASK = "masking".
# * "MAE" (default): mean absolute error (MAE or L1 loss). Ref: https://pytorch.org/docs/stable/generated/torch.nn.L1Loss.html#torch.nn.L1Loss
# * "MSE": mean square error (MSE). Ref: https://pytorch.org/docs/stable/generated/torch.nn.MSELoss.html#torch.nn.MSELoss
# * "SSIM": structural similarity index measure (SSIM). Ref: https://lightning.ai/docs/torchmetrics/stable/image/structural_similarity.html#torchmetrics.image.StructuralSimilarityIndexMeasure
# * "W_MAE_SSIM": MAE and SSIM (with a weight term on each one that must sum 1).
# * "W_MSE_SSIM": MSE and SSIM (with a weight term on each one that must sum 1).
# * Classification:
# * "CE" (default): cross entropy. Ref: https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html
# * Image to image:
# * "MAE" (default): mean absolute error (MAE or L1 loss). Ref: https://pytorch.org/docs/stable/generated/torch.nn.L1Loss.html#torch.nn.L1Loss
# * "MSE": mean square error (MSE). Ref: https://pytorch.org/docs/stable/generated/torch.nn.MSELoss.html#torch.nn.MSELoss
# * "SSIM": structural similarity index measure (SSIM). Ref: https://lightning.ai/docs/torchmetrics/stable/image/structural_similarity.html#torchmetrics.image.StructuralSimilarityIndexMeasure
# * "W_MAE_SSIM": MAE and SSIM (with a weight term on each one that must sum 1).
# * "W_MSE_SSIM": MSE and SSIM (with a weight term on each one that must sum 1).
_C.LOSS.TYPE = ""
# Weights to be applied in multiple loss combination cases, by multiplying the corresponding weight to each loss. For example, in the case of "W_CE_DICE", the final loss will be:
# LOSS.WEIGHTS[0] * CE + LOSS.WEIGHTS[1] * DICE. The length of the list must be equal to the number of losses that are combined.
_C.LOSS.WEIGHTS = [1.0, 1.0]
# To weight classes in an imbalanced dataset. Options available are:
# * 'none': no class rebalancing is applied
# * 'manual': the weights provided in LOSS.CLASS_WEIGHTS are used to weight each class. This is valid for semantic segmentation, instance segmentation (when instance+classes are predicted)
# and detection workflows (when centroids + classes are predicted).
_C.LOSS.CLASS_REBALANCE = "none"
# If LOSS.CLASS_REBALANCE is set to 'manual', this list of weights will be used to weight each class in the loss calculation.
# The length of the list must be equal to the number of classes.
_C.LOSS.CLASS_WEIGHTS = []
# Whether to ignore a value in the loss and metric calculation. This is only available when LOSS.TYPE == "CE". This value will not only
# be ignored in the loss computation but in the metrics, e.g. IoU.
_C.LOSS.IGNORE_INDEX = -1
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 6.1 Contrastive learning definitions
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.LOSS.CONTRAST = CN()
_C.LOSS.CONTRAST.ENABLE = False
_C.LOSS.CONTRAST.MEMORY_SIZE = 5000
_C.LOSS.CONTRAST.PROJ_DIM = 256
_C.LOSS.CONTRAST.PIXEL_UPD_FREQ = 10
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 7. Training phase options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.TRAIN = CN()
_C.TRAIN.ENABLE = False
# Enable verbosity
_C.TRAIN.VERBOSE = False
# Optimizer to use. Possible values: "SGD", "ADAM" or "ADAMW"
_C.TRAIN.OPTIMIZER = "SGD"
# Learning rate
_C.TRAIN.LR = 1.0e-4
# Weight decay
_C.TRAIN.W_DECAY = 0.02
# Coefficients used for computing running averages of gradient and its square. Used in ADAM and ADAMW optmizers
_C.TRAIN.OPT_BETAS = (0.9, 0.999)
# Batch size
_C.TRAIN.BATCH_SIZE = 2
# If memory or # gpus is limited, use this variable to maintain the effective batch size, which is
# batch_size (per gpu) * nodes * (gpus per node) * accum_iter.
_C.TRAIN.ACCUM_ITER = 1
# Number of epochs to train the model
_C.TRAIN.EPOCHS = 360
# Epochs to wait with no validation data improvement until the training is stopped
_C.TRAIN.PATIENCE = -1
# Metrics to apply during training. Depending on the workflow different ones can be applied. If empty, some
# default metrics will be configured automatically:
# * Semantic segmentation: 'iou' (called also Jaccard index)
# * Instance segmentation: automatically set depending on the channels selected (PROBLEM.INSTANCE_SEG.DATA_CHANNELS).
# * Detection: 'iou' (called also Jaccard index)
# * Denoising: 'mae', 'mse'
# * Super-resolution: "psnr", "mae", "mse", "ssim"
# * Self-supervision: "psnr", "mae", "mse", "ssim"
# * Classification: 'accuracy', 'top-5-accuracy'
# * Image to image: "psnr", "mae", "mse", "ssim"
_C.TRAIN.METRICS = []
# Callbacks
# To determine which value monitor to consider which epoch consider the best to save. Currently not used.
_C.TRAIN.CHECKPOINT_MONITOR = "val_loss"
# Add profiler callback to the training
# _C.TRAIN.PROFILER = False
# # Batch range to be analyzed
# _C.TRAIN.PROFILER_BATCH_RANGE='10, 100'
# _C.TRAIN.MAE_CALLBACK_EPOCHS = 5
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 7.1 Learning rate (LE) scheduler options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# LR Scheduler
_C.TRAIN.LR_SCHEDULER = CN()
_C.TRAIN.LR_SCHEDULER.NAME = "" # Possible options: 'warmupcosine', 'reduceonplateau', 'onecycle'
# Lower bound on the learning rate used in 'warmupcosine' and 'reduceonplateau'
_C.TRAIN.LR_SCHEDULER.MIN_LR = -1.0
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 7.1.1 Reduce on plateau options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The reduce on plateau scheduler reduces the learning rate when a metric has stopped improving.
#
# Factor by which the learning rate will be reduced
_C.TRAIN.LR_SCHEDULER.REDUCEONPLATEAU_FACTOR = 0.5
# Number of epochs with no improvement after which learning rate will be reduced. Need to be less than 'TRAIN.PATIENCE'
# otherwise it makes no sense
_C.TRAIN.LR_SCHEDULER.REDUCEONPLATEAU_PATIENCE = -1
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 7.1.2 Cosine decay with warm up options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Cosine decay with a warm up consist in 2 phases: 1) a warm up phase which consists of increasing
# the learning rate from TRAIN.LR_SCHEDULER.MIN_LR to TRAIN.LR value by a factor
# during a certain number of epochs defined by 'TRAIN.LR_SCHEDULER.WARMUP_COSINE_DECAY_EPOCHS'
# 2) after this will began the decay of the learning rate value using the cosine function.
# Find a detailed explanation in: https://scorrea92.medium.com/cosine-learning-rate-decay-e8b50aa455b
#
# Epochs to do the warming up.
_C.TRAIN.LR_SCHEDULER.WARMUP_COSINE_DECAY_EPOCHS = -1
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 8. Test/inference phase options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.TEST = CN()
_C.TEST.ENABLE = False
# Tries to reduce the memory footprint by separating crop/merge operations and by changing dtype of the predictions.
# It is slower and not as precise as the "normal" inference process but saves memory
_C.TEST.REDUCE_MEMORY = False
# Whether to compute the metrics in CPU instead of GPU to reduce GPU memory consumption.
_C.TEST.METRICS_IN_CPU = False
# Whether to save the raw output of the model (before any post-processing) alongside the final prediction. It is placed normally
# in a folder called 'per_image'
_C.TEST.SAVE_MODEL_RAW_OUTPUT = True
# Enable verbosity
_C.TEST.VERBOSE = True
# Make test-time augmentation. Infer over 8 possible rotations for 2D img and 16 when 3D
_C.TEST.AUGMENTATION = False
# Select test-time augmentation mode. Options: "mean" (default), "min", "max".
_C.TEST.AUGMENTATION_MODE = "mean"
# Stack 2D images into a 3D image and then process it entirely instead of going image per image
_C.TEST.ANALIZE_2D_IMGS_AS_3D_STACK = False
# Whether to reuse the existing ones (from file) or calculate predictions using the model
_C.TEST.REUSE_PREDICTIONS = False
# If PROBLEM.NDIM = '2D' this can be activated to process each image entirely instead of patch by patch. Only can be done
# if the neural network is fully convolutional. Implemented in semantic-segmentation, instance-segmentation and detection workflows.
_C.TEST.FULL_IMG = False
# Metrics to apply during test/inference. Depending on the workflow different ones can be applied. If empty, some
# default metrics will be configured automatically:
# * Semantic segmentation: 'iou' (called also Jaccard index)
# * Instance segmentation: automatically set depending on the channels selected (PROBLEM.INSTANCE_SEG.DATA_CHANNELS).
# Instance metrics will be always calculated.
# * Detection: 'iou' (called also Jaccard index)
# * Denoising: 'mae', 'mse'
# * Super-resolution: "psnr", "mae", "mse", "ssim". Additionally, if only if PROBLEM.NDIM == '2D', these
# can also be selected: "fid", "is", "lpips"
# * Self-supervision: "psnr", "mae", "mse", "ssim". Additionally, if only if PROBLEM.NDIM == '2D', these
# can also be selected: "fid", "is", "lpips"
# * Classification: 'accuracy'. Always calculated: Confusion matrix
# * Image to image: "psnr", "mae", "mse", "ssim". Additionally, if only if PROBLEM.NDIM == '2D', these
# can also be selected: "fid", "is", "lpips"
_C.TEST.METRICS = []
### Instance segmentation
# Whether to calculate matching statistics (average overlap, accuracy, recall, precision, etc.)
_C.TEST.MATCHING_STATS = True
# Theshold of overlap to consider a TP when calculating the metrics. If more than one value is provided
# the process is repeated with each of the threshold values
_C.TEST.MATCHING_STATS_THS = [0.3, 0.5, 0.75]
# Decide in which thresholds to create a colored image of the TPs, FNs and FPs
_C.TEST.MATCHING_STATS_THS_COLORED_IMG = []
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 8.1 Test/inference by chunks options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# In the processing of 3D images, the primary image is segmented into smaller patches. These patches are subsequently
# passed through a computational network. The outcome is a new image, typically saved as a TIF file, that retains the
# dimensions of the original input. Notably, if the input image is sizable, this process can be memory-intensive. This
# is because the quantity of patches is contingent on both the dimensions of the input and the selected padding/overlap
# parameters (defined as 'DATA.TEST.PADDING' and 'DATA.TEST.OVERLAP').
# To alleviate potential memory constraints, we offer an alternative: producing an H5/Zarr file with the predicted patches.
# This method ensures efficient memory usage, as patches are individually incorporated into the H5/Zarr file in their respective
# positions. This negates the need to store all patches simultaneously for image reconstruction. Importantly, in this
# approach, only the 'DATA.TEST.PADDING' parameter is considered, excluding 'DATA.TEST.OVERLAP', which sufficiently
# addresses border effect issues. If the source image is also an H5/Zarr file, it will be processed by chunks, further
# optimizing memory usage. This process can only be applied in semantic segmentation, instance segmentation and detection
# workflows.
#
_C.TEST.BY_CHUNKS = CN()
_C.TEST.BY_CHUNKS.ENABLE = False
# In the process of 'TEST.BY_CHUNKS' you can enable this variable to save the reconstructed prediction as a TIF too.
# Be aware of this option and be sure that the prediction can fit in you memory entirely, as it is needed for saving as TIF.
_C.TEST.BY_CHUNKS.SAVE_OUT_TIF = False
# In how many iterations the H5 writer needs to flush the data. No need to do so with Zarr files.
_C.TEST.BY_CHUNKS.FLUSH_EACH = 100
# Z slice index (inclusive) at which chunk processing starts. Use -1 (default) to start from the beginning.
# Useful for distributing large-volume prediction across multiple cluster jobs, each handling a Z sub-range.
_C.TEST.BY_CHUNKS.Z_START = -1
# Z slice index (exclusive) at which chunk processing ends. Use -1 (default) to process until the end.
# The output Zarr is always the full data shape so multiple jobs can write concurrently.
_C.TEST.BY_CHUNKS.Z_END = -1
# Phases to execute in this job. Allows splitting the full pipeline across multiple cluster jobs.
# Available phases:
# * 'prediction' : run the model on each patch and write raw predictions to a Zarr file.
# * 'instance_creation' : run per-chunk watershed (instance segmentation, 'chunk_by_chunk' only).
# * 'instance_merging' : resolve cross-chunk instance IDs (Passes B–E, instance segmentation only).
# Example multi-job setup for a large volume:
# Job 1 — Z_START=0, Z_END=500, PHASES=["prediction", "instance_creation"]
# Job 2 — Z_START=500, Z_END=1000, PHASES=["prediction", "instance_creation"]
# Job 3 — (no Z range) PHASES=["instance_merging"]
_C.TEST.BY_CHUNKS.PHASES = ["prediction", "instance_creation", "instance_merging"]
# After passing all the patches through the model we obtain the model's raw predictions, which may be subsequently processed
# to generate the final prediction. Each workflow has its own steps for this process:
#
# * Semantic segmentation: all raw predictions, which are probabilities of each class, are merged together to create the final
# predicted image by argmax operation. This process is not memory intensive as the raw predictions are merged patch by
# patch and not all at once.
# * Instance segmentation: the raw predictions are merged together to create the final predicted image by a watershed process.
# This process is memory intensive as the entire predicted image needs to be loaded in memory to do it.
# * Detection: All the points of interest are detected from the raw predictions. This process is not memory intensive as the
# points are detected patch by patch and not all at once.
_C.TEST.BY_CHUNKS.WORKFLOW_PROCESS = CN()
_C.TEST.BY_CHUNKS.WORKFLOW_PROCESS.ENABLE = True
# How the workflow process is going to be done. There are two options:
# * 'chunk_by_chunk' : each chunk will be considered as an individual file. Select this operation if you have not enough
# memory to process the entire prediction image with 'entire_pred'.
# * 'entire_pred': the predicted image will be loaded in memory and processed entirely (be aware of your memory budget)
_C.TEST.BY_CHUNKS.WORKFLOW_PROCESS.TYPE = "chunk_by_chunk"
# Number of voxels added on each side of a chunk before running the per-chunk watershed (instance segmentation,
# 'chunk_by_chunk' mode only). A larger halo gives each chunk more context from its neighbours so seeds near
# boundaries are correctly connected, reducing jagged artefacts at chunk seams. Set this to at least the radius
# of your largest expected instance. Increasing this value raises memory usage proportionally.
# Use -1 (default) to let BiaPy compute it automatically as patch_size / 8.
_C.TEST.BY_CHUNKS.WORKFLOW_PROCESS.INSTANCE_SEG_HALO = -1
# Minimum normalised IoU required to merge two instances across a chunk boundary
# (instance segmentation, 'chunk_by_chunk' mode only). Must be in (0, 1].
_C.TEST.BY_CHUNKS.WORKFLOW_PROCESS.INSTANCE_SEG_MERGE_IOU_TH = 0.3
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 8.2 Detection test/inference options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# To decide which function is going to be used to create point from probabilities. Options: ['peak_local_max', 'blob_log']
# 'peak_local_max': https://scikit-image.org/docs/stable/api/skimage.feature.html#skimage.feature.peak_local_max
# 'blob_log': https://scikit-image.org/docs/stable/api/skimage.feature.html#skimage.feature.blob_log
_C.TEST.DET_POINT_CREATION_FUNCTION = "peak_local_max"
# The minimal allowed distance separating peaks. To find the maximum number of peaks, use min_distance=1.
_C.TEST.DET_PEAK_LOCAL_MAX_MIN_DISTANCE = 1
# Whether the threshold are going to be set as automaticaly (with Otsu thresholding) or manually.
# Options available: 'auto' or 'manual'. If this last is used TEST.DET_MIN_TH_TO_BE_PEAK needs to be set.
_C.TEST.DET_TH_TYPE = "manual"
# Minimun value to consider a point as a peak. Corresponds to 'threshold_abs' argument of the function
# 'peak_local_max' of skimage.feature
_C.TEST.DET_MIN_TH_TO_BE_PEAK = 0.2
# Corresponds to 'exclude_border' argument of 'peak_local_max' or 'blob_log' function of skimage. If True it will exclude
# peaks from the border of the image to avoid partial detection.
_C.TEST.DET_EXCLUDE_BORDER = False
# Corresponds to 'min_sigma' argument of 'blob_log' function. It is the minimum standard deviation for Gaussian kernel.
# Keep this low to detect smaller blobs. The standard deviations of the Gaussian filter are given for each axis as a
# sequence, or as a single number, in which case it is equal for all axes.
_C.TEST.DET_BLOB_LOG_MIN_SIGMA = 5
# Corresponds to 'max_sigma' argument of 'blob_log' function. It is the maximum standard deviation for Gaussian kernel.
# Keep this high to detect larger blobs. The standard deviations of the Gaussian filter are given for each axis as a
# sequence, or as a single number, in which case it is equal for all axes.
_C.TEST.DET_BLOB_LOG_MAX_SIGMA = 10
# Corresponds to 'num_sigma' argument of 'blob_log' function. The number of intermediate values of standard deviations
# to consider between min_sigma and max_sigma.
_C.TEST.DET_BLOB_LOG_NUM_SIGMA = 2
# Maximum distance far away from a GT point to consider a point as a true positive
_C.TEST.DET_TOLERANCE = 10
# To not take into account during detection metrics calculation to those points outside the bounding box defined with
# this variable. Order is: [z, y, x] (3D) and [y, x] (2D). For example, using an image of 10x100x200 to not take into
# account points on the first/last slices and with a border of 15 pixel for x and y axes, this variable could be defined
# as [1, 15, 15].
_C.TEST.DET_IGNORE_POINTS_OUTSIDE_BOX = []
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 8.3 Post-processing options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.TEST.POST_PROCESSING = CN()
# To apply median filtering to the data
_C.TEST.POST_PROCESSING.MEDIAN_FILTER = False
# List of median filters to apply. They are going to be applied in the list order. This can only be used in
# 'SEMANTIC_SEG', 'INSTANCE_SEG' and 'DETECTION' workflows. There are multiple options to compose the list:
# * 'xy' or 'yx': to apply the filter in x and y axes together
# * 'zy' or 'yz': to apply the filter in y and z axes together
# * 'zx' or 'xz': to apply the filter in x and z axes together
# * 'z': to apply the filter only in z axis
# Those filter that imply 'z' axis are going to be applied only in 3D or in 2D if TEST.ANALIZE_2D_IMGS_AS_3D_STACK is selected
_C.TEST.POST_PROCESSING.MEDIAN_FILTER_AXIS = []
_C.TEST.POST_PROCESSING.MEDIAN_FILTER_SIZE = []
# Apply a binary mask to remove possible segmentation outside it (you need to provide the mask and it must
# contain two values: '1' -> preserve the pixel ; '0' discard pixel ). A mask for each test sample must be
# provided and it will be loaded using 'DATA.TEST.BINARY_MASKS' variable.
_C.TEST.POST_PROCESSING.APPLY_MASK = False
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 8.3.1 Instance segmentation post-processing options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Instance refinement:
# Whether to refine the instances with morphological and filtering operations after being created and before any other post-processing
# such as Voronoi. This instance refinement is applied on each instance individually and sequentially. The two variables,
# TEST.POST_PROCESSING.INSTANCE_REFINEMENT.PROPS and TEST.POST_PROCESSING.INSTANCE_REFINEMENT.VALUES of refinements to be applied.
# For instance, the conditions can be like this: ['A', 'B', 'C'] and they will be applied sequentially.
# A full example of this refinement:
# _C.DATA.VAL.FILTER_SAMPLES.PROPS = ['fill_holes', 'remove_small_objects', 'remove_large_objects', 'clear_border']
# _C.DATA.VAL.FILTER_SAMPLES.VALUES = ['none', 10, 2000, 'none']
_C.TEST.POST_PROCESSING.INSTANCE_REFINEMENT = CN()
# Enable/disable instance refinement
_C.TEST.POST_PROCESSING.INSTANCE_REFINEMENT.ENABLE = False
# List of morphological operations to apply. They are going to be applied in the list order. Available operations are:
# * 'dilation': to dilate instances
# * 'erosion': to erode instances
# * 'fill_holes': to fill holes inside instances
# * 'clear_border': to remove instances touching the image border
# * 'remove_small_objects': to remove small objects
# * 'remove_large_objects': to remove large objects
_C.TEST.POST_PROCESSING.INSTANCE_REFINEMENT.OPERATIONS = []
# Values associated to each operation. For 'dilation' and 'erosion' it corresponds to the size of the structuring element (it can also be a list).
# For 'remove_small_objects' and 'remove_large_objects' it corresponds to the size threshold in pixels.
# For 'fill_holes' and 'clear_border' no value is needed so put None in those cases.
_C.TEST.POST_PROCESSING.INSTANCE_REFINEMENT.VALUES = []
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 8.3.1.1 Instance property measurement and filtering options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Whether to measure morphological features on each instances, i.e. 'circularity' (2D), 'elongation' (2D), 'npixels', 'area', 'diameter',
# 'perimeter', 'sphericity' (3D)
_C.TEST.POST_PROCESSING.MEASURE_PROPERTIES = CN()
_C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.ENABLE = False
# List of properties to measure on each instance. The following properties will be always calculated: label, npixels, areas, centers, elongation (2D),
# sphericities (2D)/circularities (3D), diameters, perimeter (2D)/surface_area (3D). Apart from them, you can select more properties to be calculated
# based on scikit-image regionprops function. Check the following link for a detailed list of the extra available properties you can request:
# https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops
# Default property description is as follows:
# * 'circularity' is defined as the ratio of area over the square of the perimeter, normalized such that the value for a disk equals
# one: (4 * PI * area) / (perimeter^2). Only measurable for 2D images (use sphericity for 3D images). While values of circularity
# range theoretically within the interval [0;1], the measurements errors of the perimeter may produce circularity values above 1
# (Lehmann et al., 201211 ; https://doi.org/10.1093/bioinformatics/btw413).
#
# * 'elongation' is the inverse of the circularity. The values of elongation range from 1 for round particles and increase for
# elongated particles. Calculated as: (perimeter^2)/(4 * PI * area) . It is only measurable for 2D images.
#
# * 'npixels' corresponds to the sum of pixels that compose an instance.
#
# * 'area' corresponds to the number of pixels taking into account the image resolution (we call it 'area' also even in a 3D
# image for simplicity, but that will be the volume in that case). In the resulting statistics 'volume' will appear in that
# case too.
#
# * 'diameter' calculated with the bounding box and by taking the maximum value of the box in x and y axes. In 3D, z axis
# is also taken into account. Does not take into account the image resolution.
#
# * 'perimeter', in 2D, approximates the contour as a line through the centers of border pixels using a 4-connectivity. In 3D,
# it corresponds to the surface area.
#
# * 'sphericity', in 3D, it is the ratio of the squared volume over the cube of the surface area, normalized such that the value
# for a ball equals one: (36 * PI)*((volume^2)/(perimeter^3)). Only measurable for 3D images (use circularity for 2D images).
#
_C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.EXTRA_PROPS = []
# Remove instances by the conditions based in each instance properties. The three variables, TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.PROPS,
# TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.VALUES and TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.SIGNS will compose a list
# of conditions to remove the instances. They are list of list of conditions. For instance, the conditions can be like this: [['A'], ['B','C']]. Then, if the instance satisfies
# the first list of conditions, only 'A' in this first case (from ['A'] list), or satisfy 'B' and 'C' (from ['B','C'] list) it will be
# removed from the image. In each sublist all the conditions must be satisfied. Available properties are: ['circularity', 'elongation',
# 'npixels', 'area', 'diameter', 'perimeter', 'sphericity']. When this post-processing step is selected two .csv files
# will be created, one with the properties of each instance from the original image (will be placed in PATHS.RESULT_DIR.PER_IMAGE_INSTANCES
# path), and another with only instances that remain once this post-processing has been applied (will be placed in
# PATHS.RESULT_DIR.PER_IMAGE_POST_PROCESSING path). In those csv files two more information columns will appear: a list of conditions
# that each instance has satisfy or not ('Satisfied', 'No satisfied' respectively), and a comment with two possible values, 'Removed'
# and 'Correct', telling you if the instance has been removed or not, respectively. Some of the properties follow the formulas used in
# MorphoLibJ library for Fiji https://doi.org/10.1093/bioinformatics/btw413
#
# A full example of this post-processing:
# If you want to remove those instances that have less than 100 pixels and circularity less equal to 0.7 you should
# declare the above three variables as follows:
# _C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.PROPS = [['npixels', 'circularity']]
# _C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.VALUES = [[100, 0.7]]
# _C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.SIGNS = [['lt', 'le']]
# You can also concatenate more restrictions and they will be applied in order. For instance, if you want to remove those
# instances that are bigger than an specific area, and do that before the condition described above, you can define the
# variables this way:
# _C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.PROPS = [['area'], ['npixels', 'circularity']]
# _C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.VALUES = [[500], [100, 0.7]]
# _C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.SIGNS = [['gt'], ['lt', 'le']]
# This way, the instances will be removed by 'area' and then by 'npixels' and 'circularity'
_C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES = CN()
# Whether to enable or not the filtering by properties
_C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.ENABLE = False
# List of lists of properties to apply a filter. Available properties are: ['circularity', 'elongation', 'npixels', 'area', 'diameter',
# 'perimeter', 'sphericity']
_C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.PROPS = []
# List of ints/float that represent the values of the properties listed in TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES
# that the instances need to satisfy to not be dropped.
_C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.VALUES = []
# List of list of signs to do the comparison. Options: ['gt', 'ge', 'lt', 'le'] that corresponds to "greather than", e.g. ">",
# "greather equal", e.g. ">=", "less than", e.g. "<", and "less equal" e.g. "<=" comparisons.
_C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.SIGNS = []
# Whether to apply Voronoi using 'BC' or 'M' channels need to be present
_C.TEST.POST_PROCESSING.VORONOI_ON_MASK = False
# Threshold to be applied to the 'M' channel when expanding the instances with Voronoi. Need to be in [0,1] range.
# Leave it to 0 to adjust the threhold with Otsu
_C.TEST.POST_PROCESSING.VORONOI_TH = 0.0
# Set it to try to repare large instances by merging their neighbors with them and removing possible central holes.
# Its value determines which instances are going to be repared by size (number of pixels that compose the instance)
# This option is useful when PROBLEM.INSTANCE_SEG.DATA_CHANNELS is 'BP', as multiple central seeds may appear in big
# instances. Only works in Instance segmentation workflow.
_C.TEST.POST_PROCESSING.REPARE_LARGE_BLOBS_SIZE = -1
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 8.3.2 Detection post-processing options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# To remove close points to each other. This can also be set when using 'BP' channels for instance segmentation.
_C.TEST.POST_PROCESSING.REMOVE_CLOSE_POINTS = False
# Distance between points to be considered the same. Only applies when TEST.POST_PROCESSING.REMOVE_CLOSE_POINTS = True
# This can also be set when using 'BP' channels for instance segmentation.
_C.TEST.POST_PROCESSING.REMOVE_CLOSE_POINTS_RADIUS = 0
# Whether to apply a watershed to grow the points detected
_C.TEST.POST_PROCESSING.DET_WATERSHED = False
# Structure to dilate the initial seeds before watershed. For instance in a 3D problem: [10,10,4]
_C.TEST.POST_PROCESSING.DET_WATERSHED_FIRST_DILATION = [-1, -1]
# List of classes to be consider as 'donuts'. For those class points, the 'donuts' type cell means that their nucleus is
# to big and that the seeds need to be dilated more so the watershed can grow the instances properly.
_C.TEST.POST_PROCESSING.DET_WATERSHED_DONUTS_CLASSES = [-1]
# Patch shape to extract all donuts type cells. It needs to be a bit greater than bigest donuts type cell so all of them can
# be contained in this patch. This is used to analize that area for each point of class `DET_WATERSHED_DONUTS_CLASSES`.
_C.TEST.POST_PROCESSING.DET_WATERSHED_DONUTS_PATCH = [13, 120, 120]
# Diameter (in pixels) that a cell need to have to be considered as donuts type
_C.TEST.POST_PROCESSING.DET_WATERSHED_DONUTS_NUCLEUS_DIAMETER = 30
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 9. Auxiliary paths
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.PATHS = CN()
# Directories to store the results
_C.PATHS.RESULT_DIR = CN()
_C.PATHS.RESULT_DIR.PATH = os.path.join(job_dir, "results", job_identifier)
_C.PATHS.RESULT_DIR.PER_IMAGE = os.path.join(_C.PATHS.RESULT_DIR.PATH, "per_image")
_C.PATHS.RESULT_DIR.PER_IMAGE_BIN = os.path.join(_C.PATHS.RESULT_DIR.PATH, "per_image_binarized")
_C.PATHS.RESULT_DIR.PER_IMAGE_INSTANCES = os.path.join(_C.PATHS.RESULT_DIR.PATH, "per_image_instances")
_C.PATHS.RESULT_DIR.PER_IMAGE_POST_PROCESSING = os.path.join(
_C.PATHS.RESULT_DIR.PATH, "per_image_post_processing"
)
_C.PATHS.RESULT_DIR.FULL_IMAGE = os.path.join(_C.PATHS.RESULT_DIR.PATH, "full_image")
_C.PATHS.RESULT_DIR.FULL_IMAGE_BIN = os.path.join(_C.PATHS.RESULT_DIR.PATH, "full_image_binarized")
_C.PATHS.RESULT_DIR.FULL_IMAGE_INSTANCES = os.path.join(_C.PATHS.RESULT_DIR.PATH, "full_image_instances")
_C.PATHS.RESULT_DIR.FULL_IMAGE_POST_PROCESSING = os.path.join(
_C.PATHS.RESULT_DIR.PATH, "full_image_post_processing"
)
_C.PATHS.RESULT_DIR.AS_3D_STACK = os.path.join(_C.PATHS.RESULT_DIR.PATH, "as_3d_stack")
_C.PATHS.RESULT_DIR.AS_3D_STACK_BIN = os.path.join(_C.PATHS.RESULT_DIR.PATH, "as_3d_stack_binarized")
_C.PATHS.RESULT_DIR.AS_3D_STACK_POST_PROCESSING = os.path.join(
_C.PATHS.RESULT_DIR.PATH, "as_3d_stack_post_processing"
)
_C.PATHS.RESULT_DIR.DET_LOCAL_MAX_COORDS_CHECK = os.path.join(
_C.PATHS.RESULT_DIR.PATH, "per_image_local_max_check"
)
_C.PATHS.RESULT_DIR.DET_LOCAL_MAX_COORDS_CHECK_POST_PROCESSING = os.path.join(
_C.PATHS.RESULT_DIR.PATH, "per_image_local_max_check_post_processing"
)
_C.PATHS.RESULT_DIR.DET_ASSOC_POINTS = os.path.join(_C.PATHS.RESULT_DIR.PATH, "point_associations")
_C.PATHS.RESULT_DIR.INST_ASSOC_POINTS = os.path.join(_C.PATHS.RESULT_DIR.PATH, "instance_associations")
# Path to store the BMZ model created
_C.PATHS.BMZ_EXPORT_PATH = os.path.join(_C.PATHS.RESULT_DIR.PATH, "BMZ_files")
# Path to store profiler files
_C.PATHS.PROFILER = os.path.join(_C.PATHS.RESULT_DIR.PATH, "profiler")
# Name of the folder where the charts of the loss and metrics values while training the network are stored.
_C.PATHS.CHARTS = os.path.join(_C.PATHS.RESULT_DIR.PATH, "charts")
# Folder where samples of DA will be stored
_C.PATHS.DA_SAMPLES = os.path.join(_C.PATHS.RESULT_DIR.PATH, "aug")
# Folder where generator samples (X) will be stored
_C.PATHS.GEN_CHECKS = os.path.join(_C.PATHS.RESULT_DIR.PATH, "gen_check")
# Folder where generator samples (Y) will be stored
_C.PATHS.GEN_MASK_CHECKS = os.path.join(_C.PATHS.RESULT_DIR.PATH, "gen_mask_check")
# Paths where a few samples of instance channels created will be stored just to check id there is any problem
_C.PATHS.TRAIN_INSTANCE_CHANNELS_CHECK = os.path.join(
_C.PATHS.RESULT_DIR.PATH,
"train_" + "".join(_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS) + "_instance_channels",
)
_C.PATHS.VAL_INSTANCE_CHANNELS_CHECK = os.path.join(
_C.PATHS.RESULT_DIR.PATH,
"val_" + "".join(_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS) + "_instance_channels",
)
_C.PATHS.TEST_INSTANCE_CHANNELS_CHECK = os.path.join(
_C.PATHS.RESULT_DIR.PATH,
"test_" + "".join(_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS) + "_instance_channels",
)
# Name of the folder where weights files will be stored/loaded from.
_C.PATHS.CHECKPOINT = os.path.join(job_dir, "checkpoints")
# Checkpoint file to load/store the model weights
_C.PATHS.CHECKPOINT_FILE = ""
# Name of the folder to store the probability map to avoid recalculating it on every run
_C.PATHS.PROB_MAP_DIR = os.path.join(job_dir, "prob_map")
_C.PATHS.PROB_MAP_FILENAME = "prob_map.npy"
# Watershed debugging folder
_C.PATHS.WATERSHED_DIR = os.path.join(_C.PATHS.RESULT_DIR.PATH, "watershed")
# Path where the images used in MAE will be saved suring inference
_C.PATHS.MAE_OUT_DIR = os.path.join(_C.PATHS.RESULT_DIR.PATH, "MAE_checks")
# Directory to save filtered images.
_C.PATHS.FIL_SAMPLES_DIR = os.path.join(_C.PATHS.RESULT_DIR.PATH, "filtering_information")
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 10. Logging
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_C.LOG = CN()
_C.LOG.LOG_DIR = os.path.join(job_dir, "train_logs")
_C.LOG.TENSORBOARD_LOG_DIR = os.path.join(_C.PATHS.RESULT_DIR.PATH, "tensorboard")
_C.LOG.LOG_FILE_PREFIX = job_identifier
_C.LOG.CHART_CREATION_FREQ = 5
self._C = _C
[docs]
def get_cfg_defaults(self) -> CN:
"""
Get a clone of the default configuration.
Returns
-------
CN
A cloned YACS CfgNode object with default values.
"""
# Return a clone so that the defaults will not be altered
# This is for the "local variable" use pattern
return self._C.clone()
[docs]
def to_dict(self):
"""
Convert the configuration to a Python dictionary.
Returns
-------
dict
Dictionary representation of the configuration.
"""
return dict(self._C)
[docs]
def copy(self):
"""
Create a deep copy of the Config object.
Returns
-------
Config
A deep copy of the current Config instance.
"""
return copy.deepcopy(self)
def __str__(self):
"""
Return a string representation of the Config object.
Returns
-------
str
String representation of the configuration.
"""
return str(self.__dict__)
def __repr__(self):
"""
Return a string representation of the Config object.
Returns
-------
str
String representation of the configuration.
"""
return str(self.__dict__)
[docs]
def update_dependencies(cfg) -> None:
"""
Update dependent configuration variables after merging user config.
This function should be called after merging a user-provided .cfg file
to ensure that all dependent paths and variables are updated accordingly.
That is, this function should be called after YACS's merge_from_file().
Parameters
----------
cfg : Config or CN
The configuration object to update.
"""
call = getattr(cfg, "_C") if bool(getattr(cfg, "_C", False)) else cfg
# Remove possible / characters at the end of the paths
call.DATA.TRAIN.PATH = (
call.DATA.TRAIN.PATH if call.DATA.TRAIN.PATH[-1] != "/" else call.DATA.TRAIN.PATH[:-1]
)
call.DATA.TRAIN.GT_PATH = (
call.DATA.TRAIN.GT_PATH if call.DATA.TRAIN.GT_PATH[-1] != "/" else call.DATA.TRAIN.GT_PATH[:-1]
)
call.DATA.VAL.PATH = (
call.DATA.VAL.PATH if call.DATA.VAL.PATH[-1] != "/" else call.DATA.VAL.PATH[:-1]
)
call.DATA.VAL.GT_PATH = (
call.DATA.VAL.GT_PATH if call.DATA.VAL.GT_PATH[-1] != "/" else call.DATA.VAL.GT_PATH[:-1]
)
call.DATA.TEST.PATH = (
call.DATA.TEST.PATH if call.DATA.TEST.PATH[-1] != "/" else call.DATA.TEST.PATH[:-1]
)
call.DATA.TEST.GT_PATH = (
call.DATA.TEST.GT_PATH if call.DATA.TEST.GT_PATH[-1] != "/" else call.DATA.TEST.GT_PATH[:-1]
)
tdata = call.DATA.TRAIN.GT_PATH if not call.DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA else call.DATA.TRAIN.PATH
call.DATA.TRAIN.INSTANCE_CHANNELS_MASK_DIR = tdata
cpd = '_'.join([str(x) for x in call.PROBLEM.DETECTION.CENTRAL_POINT_DILATION])
call.DATA.TRAIN.DETECTION_MASK_DIR = call.DATA.TRAIN.GT_PATH + "_detection_masks_" + str(cpd)
call.DATA.TRAIN.SSL_SOURCE_DIR = call.DATA.TRAIN.PATH + "_ssl_source"
vdata = call.DATA.VAL.GT_PATH if not call.DATA.VAL.INPUT_ZARR_MULTIPLE_DATA else call.DATA.VAL.PATH
call.DATA.VAL.INSTANCE_CHANNELS_MASK_DIR = vdata
# If value is not the default
call.DATA.VAL.DETECTION_MASK_DIR = call.DATA.VAL.GT_PATH + "_detection_masks_" + str(cpd)
call.DATA.VAL.SSL_SOURCE_DIR = call.DATA.VAL.PATH + "_ssl_source"
tdata = call.DATA.TEST.GT_PATH if not call.DATA.TEST.INPUT_ZARR_MULTIPLE_DATA else call.DATA.TEST.PATH
call.DATA.TEST.INSTANCE_CHANNELS_MASK_DIR = tdata
# If value is not the default
if call.DATA.TEST.BINARY_MASKS == os.path.join("user_data", "test", "bin_mask"):
call.DATA.TEST.BINARY_MASKS = os.path.join(call.DATA.TEST.PATH, "..", "bin_mask")
call.DATA.TEST.DETECTION_MASK_DIR = call.DATA.TEST.GT_PATH + "_detection_masks_" + str(cpd)
call.DATA.TEST.SSL_SOURCE_DIR = call.DATA.TEST.PATH + "_ssl_source"
call.PATHS.TEST_FULL_GT_H5 = os.path.join(call.DATA.TEST.GT_PATH, "h5")
call.PATHS.TRAIN_INSTANCE_CHANNELS_CHECK = os.path.join(
call.PATHS.RESULT_DIR.PATH,
"train_" + "".join(call.PROBLEM.INSTANCE_SEG.DATA_CHANNELS) + "_instance_channels",
)
call.PATHS.VAL_INSTANCE_CHANNELS_CHECK = os.path.join(
call.PATHS.RESULT_DIR.PATH,
"val_" + "".join(call.PROBLEM.INSTANCE_SEG.DATA_CHANNELS) + "_instance_channels",
)
call.PATHS.TEST_INSTANCE_CHANNELS_CHECK = os.path.join(
call.PATHS.RESULT_DIR.PATH,
"test_" + "".join(call.PROBLEM.INSTANCE_SEG.DATA_CHANNELS) + "_instance_channels",
)