Beispiel #1
0
    class scale_range(SharedProcessingSchema):
        bioimageio_description = "Scale with percentiles."
        mode = fields.ProcMode(required=True, valid_modes=("per_dataset", "per_sample"))
        axes = fields.Axes(
            required=True,
            valid_axes="czyx",
            bioimageio_description="The subset of axes to normalize jointly. For example xy to normalize the two image "
            "axes for 2d data jointly. The batch axis (b) is not valid here.",
        )
        min_percentile = fields.Float(
            default=0,
            validate=field_validators.Range(0, 100, min_inclusive=True, max_inclusive=False),
            bioimageio_description="The lower percentile used for normalization, in range 0 to 100. Default value: 0.",
        )
        max_percentile = fields.Float(
            default=100,
            validate=field_validators.Range(1, 100, min_inclusive=False, max_inclusive=True),
            bioimageio_description="The upper percentile used for normalization, in range 1 to 100. Has to be bigger "
            "than min_percentile. Default value: 100. The range is 1 to 100 instead of 0 to 100 to avoid mistakenly "
            "accepting percentiles specified in the range 0.0 to 1.0.",
        )
        eps = fields.Float(
            missing=1e-6,
            bioimageio_description="Epsilon for numeric stability: "
            "`out = (tensor - v_lower) / (v_upper - v_lower + eps)`; "
            "with `v_lower,v_upper` values at the respective percentiles. Default value: 10^-6.",
        )

        @validates_schema
        def min_smaller_max(self, data, **kwargs):
            min_p = data.get("min_percentile", 0)
            max_p = data.get("max_percentile", 100)
            if min_p >= max_p:
                raise ValidationError(f"min_percentile {min_p} >= max_percentile {max_p}")
Beispiel #2
0
    class scale_linear(SharedProcessingSchema):
        bioimageio_description = "Fixed linear scaling."
        axes = fields.Axes(
            required=True,
            valid_axes="czyx",
            bioimageio_description="The subset of axes to scale jointly. "
            "For example xy to scale the two image axes for 2d data jointly. "
            "The batch axis (b) is not valid here.",
        )
        gain = fields.Array(
            fields.Float(), missing=fields.Float(missing=1.0), bioimageio_description="multiplicative factor"
        )  # todo: check if gain match input axes
        offset = fields.Array(
            fields.Float(), missing=fields.Float(missing=0.0), bioimageio_description="additive term"
        )  # todo: check if offset match input axes

        @validates_schema
        def either_gain_or_offset(self, data, **kwargs):
            gain = data["gain"]
            if isinstance(gain, (float, int)):
                gain = [gain]

            offset = data["offset"]
            if isinstance(offset, (float, int)):
                offset = [offset]

            if all(g == 1.0 for g in gain) and all(off == 0 for off in offset):
                raise ValidationError("Specify gain!=1.0 or offset!=0.0")
Beispiel #3
0
    class zero_mean_unit_variance(SharedProcessingSchema):
        bioimageio_description = "Subtract mean and divide by variance."
        mode = fields.ProcMode(required=True)
        axes = fields.Axes(
            required=True,
            valid_axes="czyx",
            bioimageio_description="The subset of axes to normalize jointly. For example xy to normalize the two image "
            "axes for 2d data jointly. The batch axis (b) is not valid here.",
        )
        mean = fields.Array(
            fields.Float(),
            bioimageio_description="The mean value(s) to use for `mode == fixed`. For example `[1.1, 2.2, 3.3]` in the "
            "case of a 3 channel image where the channels are not normalized jointly.",
        )  # todo: check if means match input axes (for mode 'fixed')
        std = fields.Array(
            fields.Float(),
            bioimageio_description="The standard deviation values to use for `mode == fixed`. Analogous to mean.",
        )
        eps = fields.Float(
            missing=1e-6,
            bioimageio_description="epsilon for numeric stability: `out = (tensor - mean) / (std + eps)`. "
            "Default value: 10^-6.",
        )

        @validates_schema
        def mean_and_std_match_mode(self, data, **kwargs):
            if data["mode"] == "fixed" and ("mean" not in data or "std" not in data):
                raise ValidationError(
                    "`kwargs` for 'zero_mean_unit_variance' preprocessing with `mode` 'fixed' require additional "
                    "`kwargs`: `mean` and `std`."
                )
            elif data["mode"] != "fixed" and ("mean" in data or "std" in data):
                raise ValidationError(
                    "`kwargs`: `mean` and `std` for 'zero_mean_unit_variance' preprocessing are only valid for `mode` 'fixed'."
                )
Beispiel #4
0
class _TensorBase(_BioImageIOSchema):
    name = fields.String(
        required=True,
        validate=field_validators.Predicate("isidentifier"),
        bioimageio_description="Tensor name. No duplicates are allowed.",
    )
    description = fields.String()
    axes = fields.Axes(
        required=True,
        bioimageio_description=
        """Axes identifying characters from: bitczyx. Same length and order as the axes in `shape`.

| character | description |
| --- | --- |
|  b  |  batch (groups multiple samples) |
|  i  |  instance/index/element |
|  t  |  time |
|  c  |  channel |
|  z  |  spatial dimension z |
|  y  |  spatial dimension y |
|  x  |  spatial dimension x |""",
    )
    data_type = fields.String(
        required=True,
        bioimageio_description=
        "The data type of this tensor. For inputs, only `float32` is allowed and the consumer "
        "software needs to ensure that the correct data type is passed here. For outputs can be any of `float32, "
        "float64, (u)int8, (u)int16, (u)int32, (u)int64`. The data flow in bioimage.io models is explained "
        "[in this diagram.](https://docs.google.com/drawings/d/1FTw8-Rn6a6nXdkZ_SkMumtcjvur9mtIhRqLwnKqZNHM/edit).",
    )
    data_range = fields.Tuple(
        (fields.Float(allow_nan=True), fields.Float(allow_nan=True)),
        bioimageio_description=
        "Tuple `(minimum, maximum)` specifying the allowed range of the data in this tensor. "
        "If not specified, the full data range that can be expressed in `data_type` is allowed.",
    )
    shape: fields.Union

    processing_name: str

    @validates_schema
    def validate_processing_kwargs(self, data, **kwargs):
        axes = data.get("axes", [])
        processing_list = data.get(self.processing_name, [])
        for processing in processing_list:
            kwargs = processing.kwargs or {}
            kwarg_axes = kwargs.get("axes", "")
            if any(a not in axes for a in kwarg_axes):
                raise ValidationError(
                    "`kwargs.axes` needs to be subset of axes")
Beispiel #5
0
class ImplicitOutputShape(SharedBioImageIOSchema):
    reference_tensor = fields.String(required=True, bioimageio_description="Name of the reference tensor.")
    scale = fields.List(
        fields.Float(), required=True, bioimageio_description="'output_pix/input_pix' for each dimension."
    )
    offset = fields.List(
        fields.Float(), required=True, bioimageio_description="Position of origin wrt to input. Multiple of 0.5."
    )

    @validates_schema
    def matching_lengths(self, data, **kwargs):
        scale = data["scale"]
        offset = data["offset"]
        if len(scale) != len(offset):
            raise ValidationError(f"scale {scale} has to have same length as offset {offset}!")

    @validates("offset")
    def double_offset_is_int(self, value: List[float]):
        for v in value:
            if 2 * v != int(2 * v):
                raise ValidationError(f"offset {v} in {value} not a multiple of 0.5!")
Beispiel #6
0
 class clip(SharedProcessingSchema):
     bioimageio_description = "Set tensor values below min to min and above max to max."
     min = fields.Float(required=True, bioimageio_description="minimum value for clipping")
     max = fields.Float(required=True, bioimageio_description="maximum value for clipping")
Beispiel #7
0
 class binarize(SharedProcessingSchema):
     bioimageio_description = (
         "Binarize the tensor with a fixed threshold, values above the threshold will be set to one, values below "
         "the threshold to zero."
     )
     threshold = fields.Float(required=True, bioimageio_description="The fixed threshold")