def _validate_inputs(self):
        """Checks that the inputs meet their validation criteria

        `'image'` must be derived from a BaseImageContainer
        `'affine'` must be a numpy.ndarray of shape (4,4)
        `'shape'` must be a Tuple of integers of length 3

        """
        input_validator = ParameterValidator(
            parameters={
                self.KEY_IMAGE:
                Parameter(
                    validators=[isinstance_validator(BaseImageContainer)]),
                self.KEY_AFFINE:
                Parameter(validators=[isinstance_validator(np.ndarray)]),
                self.KEY_SHAPE:
                Parameter(validators=[
                    isinstance_validator(tuple),
                    for_each_validator(isinstance_validator(int)),
                ]),
            })
        input_validator.validate(self.inputs,
                                 error_type=FilterInputValidationError)

        # Further validation that can't be handled bby the parameter validator
        # check that ResampleFilter.KEY_AFFINE is of size 4x4
        if self.inputs[self.KEY_AFFINE].shape != (4, 4):
            raise FilterInputValidationError

        # Check that the tuple ResampleFilter.KEY_SHAPE has length 3
        if len(self.inputs[self.KEY_SHAPE]) != 3:
            raise FilterInputValidationError
def test_parameter_validator_change_error_type():
    """ Test that the appropriate error type is raised when user-specified """

    parameter_validator = ParameterValidator(
        {"b_number": Parameter(list_of_type_validator(str))})

    with pytest.raises(RuntimeError):
        parameter_validator.validate({}, error_type=RuntimeError)
def test_parameter_validator_valid():
    """ Test the parameter validator with some valid example data """
    parameter_validator = ParameterValidator({
        "foo":
        Parameter(reserved_string_list_validator(["foo", "bar"])),
        "bar":
        Parameter(non_empty_list_validator(), default_value=[1, 2, 3]),
    })
    assert parameter_validator.validate({"foo": "bar foo bar"}) == {
        "foo": "bar foo bar",
        "bar": [1, 2, 3],
    }  # no ValidationError raised
def test_parameter_validator_valid_with_optional_parameters():
    """Test the parameter validator with some valid example data
    including a (missing) optional parameter"""
    parameter_validator = ParameterValidator({
        "foo":
        Parameter(reserved_string_list_validator(["foo", "bar"])),
        "bar":
        Parameter(non_empty_list_validator(), optional=True),
    })
    assert parameter_validator.validate({"foo": "bar foo bar"}) == {
        "foo": "bar foo bar"
    }  # no ValidationError raised
def test_parameter_validator_missing_required():
    """ Test the parameter validator with some valid example data """
    parameter_validator = ParameterValidator({
        "foo":
        Parameter(reserved_string_list_validator(["foo", "bar"])),
        "bar":
        Parameter(non_empty_list_validator()),
    })

    with pytest.raises(
            ValidationError,
            match=
            "bar is a required parameter and is not in the input dictionary",
    ):
        parameter_validator.validate({"foo": "bar foo bar"})
    def _validate_inputs(self):
        """Checks that the inputs meet their validation criteria
        'image' must be derived from BaseImageContainer
        'metadata' must be a dict
        """

        input_validator = ParameterValidator(
            parameters={
                self.KEY_IMAGE:
                Parameter(validators=isinstance_validator(BaseImageContainer)),
                self.KEY_METADATA:
                Parameter(validators=isinstance_validator(dict)),
            })

        input_validator.validate(self.inputs,
                                 error_type=FilterInputValidationError)
def test_parameter_validator_bad_error_type():
    """ Test that a TypeError is raised if a bad error type is given to the validator """

    parameter_validator = ParameterValidator({})
    with pytest.raises(TypeError):
        parameter_validator.validate({}, error_type="foo")
    with pytest.raises(TypeError):
        parameter_validator.validate({}, error_type="foo")

    parameter_validator.validate(
        {}, error_type=ValidationError)  # sanity check - should be allowed
    def _validate_inputs(self):
        """Validate the inputs.
        'image' must be derived from BaseImageContainer and have
        an  ``image_type`` attribute that is not equal to 'PHASE_IMAGE_TYPE'.
        """
        input_validator = ParameterValidator(
            parameters={
                self.KEY_IMAGE: Parameter(
                    validators=[isinstance_validator(BaseImageContainer),]
                )
            }
        )
        input_validator.validate(self.inputs, error_type=FilterInputValidationError)

        # raise an error if the input image is a phase image.
        if self.inputs[self.KEY_IMAGE].image_type == PHASE_IMAGE_TYPE:
            raise FilterInputValidationError(
                "input 'image' has attribute 'image_type' with value 'PHASE_IMAGE_TYPE', this is"
                "not supported"
            )
 def _validate_inputs(self):
     """Validate the inputs.
     'image' must be derived from BaseImageContainer
     'scale' (optional) must be a float or integer
     'offset' (optional) must be a float or integer
     """
     input_validator = ParameterValidator(
         parameters={
             self.KEY_IMAGE:
             Parameter(validators=[
                 isinstance_validator(BaseImageContainer),
             ]),
             self.KEY_SCALE:
             Parameter(validators=[isinstance_validator((int, float))],
                       optional=True),
             self.KEY_OFFSET:
             Parameter(validators=[isinstance_validator((int, float))],
                       optional=True),
         })
     input_validator.validate(self.inputs,
                              error_type=FilterInputValidationError)
def test_parameter_validator_multiple_errors():
    """ Test that multiple errors are correctly reported by the validator """
    parameter_validator = ParameterValidator({
        "a_number":
        Parameter(
            [range_inclusive_validator(1, 2),
             from_list_validator([1.5, 1.6])]),
        "b_number":
        Parameter(list_of_type_validator(str)),
    })
    parameter_validator.validate({
        "a_number": 1.5,
        "b_number": ["foo", "bar"]
    })  # OK

    with pytest.raises(
            ValidationError,
            match=
            r"^Parameter a_number with value 0.9 does not meet the following criterion: "
            r"Value\(s\) must be between 1 and 2 \(inclusive\)\. Parameter a_number with value 0.9 "
            r"does not meet the following criterion: Value must be in \[1.5, 1.6\]\. "
            r"Parameter b_number with value \[1, 2\] does not meet the following criterion: "
            r"Value must be a list of type str$",
    ):
        parameter_validator.validate({"a_number": 0.9, "b_number": [1, 2]})
    def _validate_inputs(self):
        """
        'image' must be derived from BaseImageContainer
        'snr' must be a positive float
        'reference_image' if present must be derived from BaseImageContainer.
        image.shape and reference_image.shape must be equal
        """
        input_validator = ParameterValidator(
            parameters={
                self.KEY_IMAGE:
                Parameter(validators=isinstance_validator(BaseImageContainer)),
                self.KEY_SNR:
                Parameter(validators=[
                    isinstance_validator(float),
                    greater_than_equal_to_validator(0),
                ]),
                self.KEY_REF_IMAGE:
                Parameter(validators=isinstance_validator(BaseImageContainer),
                          optional=True),
            })

        input_validator.validate(self.inputs,
                                 error_type=FilterInputValidationError)

        # If 'reference_image' is supplied, check that its dimensions match 'image'
        if self.KEY_REF_IMAGE in self.inputs:
            input_reference_image = self.inputs[self.KEY_REF_IMAGE]
            input_image = self.inputs[self.KEY_IMAGE]
            if not isinstance(input_reference_image, BaseImageContainer):
                raise FilterInputValidationError(
                    f"Input 'reference_image' is not a BaseImageContainer"
                    f"(is {type(input_reference_image)})")
            if not input_image.shape == input_reference_image.shape:
                raise FilterInputValidationError(
                    f"Shape of inputs 'image' and 'reference_image' are not equal"
                    f"Shape of 'image' is {input_image.shape}"
                    f"Shape of 'reference_image' is {input_reference_image.shape}"
                )
 def _validate_inputs(self):
     """
     'image' must be derived from BaseImageContainer.
     'snr' must be a float and >= 0
     'reference_image' if present must be derived from BaseImageContainer
     """
     input_validator = ParameterValidator(
         parameters={
             self.KEY_IMAGE: Parameter(
                 validators=isinstance_validator(BaseImageContainer)
             ),
             self.KEY_SNR: Parameter(
                 validators=[
                     isinstance_validator(float),
                     greater_than_equal_to_validator(0),
                 ]
             ),
             self.KEY_REF_IMAGE: Parameter(
                 validators=isinstance_validator(BaseImageContainer), optional=True
             ),
         }
     )
     input_validator.validate(self.inputs, error_type=FilterInputValidationError)
def test_parameter_validator_multiple_validators():
    """ Test the parameter validator with multiple validators """
    parameter_validator = ParameterValidator({
        "a_number":
        Parameter(
            [range_inclusive_validator(1, 2),
             from_list_validator([1.5, 1.6])])
    })
    parameter_validator.validate({"a_number": 1.5})  # OK

    with pytest.raises(
            ValidationError,
            match=
            r"Parameter a_number with value 1.7 does not meet the following "
            r"criterion: Value must be in \[1.5, 1.6\]",
    ):
        parameter_validator.validate({"a_number": 1.7})
Пример #14
0
    def _validate_inputs(self):
        """Checks that the inputs meet their validation criteria.
        'image': NiftiImageContainer, must be 5D, 5th dimension same length as 'quantities'
        'quantities': list[str]
        'units': list[str]
        'segmentation': dict
        'parameters': dict
        'image_override': dict (optional)
        'parameter_override': dict (optional)
        The number of 'units' and 'quantities' should be equal.
        The size of the 5th dimension of the image must equal the number of 'quantities'.
        If 'image_override' is present, must be a dict, each of the keys must be a string
        and the values a float or int type. The key must match an entry in 'quantities'.
        If 'parameter_override' is present, must be a dict, each of the keys must be a
        string and the values a float or int type.
        """
        input_validator = ParameterValidator(
            parameters={
                self.KEY_IMAGE: Parameter(
                    validators=isinstance_validator(NiftiImageContainer)
                ),
                self.KEY_QUANTITIES: Parameter(
                    validators=for_each_validator(isinstance_validator(str))
                ),
                self.KEY_UNITS: Parameter(
                    validators=for_each_validator(isinstance_validator(str))
                ),
                self.KEY_SEGMENTATION: Parameter(validators=isinstance_validator(dict)),
                self.KEY_PARAMETERS: Parameter(validators=isinstance_validator(dict)),
                self.KEY_GROUND_TRUTH_MODULATE: Parameter(
                    validators=isinstance_validator(dict), optional=True
                ),
            }
        )
        input_validator.validate(self.inputs, error_type=FilterInputValidationError)

        image_container: NiftiImageContainer = self.inputs["image"]
        if len(image_container.shape) != 5:
            raise FilterInputValidationError(
                f"{self} filter requires an input nifti which is 5D"
            )

        if image_container.shape[4] != len(self.inputs["quantities"]):
            raise FilterInputValidationError(
                f"{self} filter requires an input nifti which has the "
                "same number of images (across the 5th dimension) as the JSON filter "
                "supplies in 'quantities'"
            )

        if len(self.inputs["units"]) != len(self.inputs["quantities"]):
            raise FilterInputValidationError(
                f"{self} filter requires an input 'units' which is the same length as the input "
                "'quantities'"
            )

        for input_key in [self.KEY_IMAGE_OVERRIDE, self.KEY_PARAMETER_OVERRIDE]:
            if input_key in self.inputs:
                # Check the value is a dictionary
                if not isinstance(self.inputs[input_key], dict):
                    raise FilterInputValidationError(
                        f"{input_key} must be a dictionary, is {self.inputs[input_key]}"
                    )
                # Check all of the keys are strings and the values are int or float
                for key, value in self.inputs[input_key].items():
                    if not isinstance(key, str):
                        raise FilterInputValidationError(
                            f"All keys in the {input_key} dictionary must be strings. "
                            f"{key} is not."
                        )
                    if not isinstance(value, (int, float)):
                        raise FilterInputValidationError(
                            f"Values in the {input_key} dictionary must be int or float. "
                            f"The value for {key} ({value}) is not."
                        )

        if self.KEY_IMAGE_OVERRIDE in self.inputs:
            # Check all of the keys are present in self.inputs['quantities']
            for key, value in self.inputs[self.KEY_IMAGE_OVERRIDE].items():
                if key not in self.inputs[self.KEY_QUANTITIES]:
                    raise FilterInputValidationError(
                        f"{key} is not in the input 'quantities' list"
                    )
        if self.KEY_GROUND_TRUTH_MODULATE in self.inputs:
            try:
                jsonschema.validate(
                    self.inputs[self.KEY_GROUND_TRUTH_MODULATE],
                    SCHEMAS["input_params"]["properties"]["global_configuration"][
                        "properties"
                    ]["ground_truth_modulate"],
                )
            except jsonschema.ValidationError as exception:
                raise FilterInputValidationError from exception
Пример #15
0
    def _validate_inputs(self):
        """Checks that the inputs meet their validation criteria
        'perfusion_rate' must be derived from BaseImageContainer and be >= 0
        'transit_time' must be derived from BaseImageContainer and be >= 0
        'm0' must be either a float or derived from BaseImageContainer and be >= 0
        'label_type' must be a string and equal to "CASL" OR "pCASL" OR "PASL"
        'label_duration" must be a float between 0 and 100
        'signal_time' must be a float between 0 and 100
        'label_efficiency' must be a float between 0 and 1
        'lambda_blood_brain' must be a float between 0 and 1
        't1_arterial_blood' must be a float between 0 and 100

        all BaseImageContainers supplied should be the same dimensions
        """
        input_validator = ParameterValidator(
            parameters={
                self.KEY_PERFUSION_RATE:
                Parameter(validators=[
                    greater_than_equal_to_validator(0),
                    isinstance_validator(BaseImageContainer),
                ]),
                self.KEY_TRANSIT_TIME:
                Parameter(validators=[
                    greater_than_equal_to_validator(0),
                    isinstance_validator(BaseImageContainer),
                ]),
                self.KEY_M0:
                Parameter(validators=[
                    greater_than_equal_to_validator(0),
                    isinstance_validator((BaseImageContainer, float)),
                ]),
                self.KEY_T1_TISSUE:
                Parameter(validators=[
                    range_inclusive_validator(0, 100),
                    isinstance_validator(BaseImageContainer),
                ]),
                self.KEY_LABEL_TYPE:
                Parameter(validators=from_list_validator(
                    [self.CASL, self.PCASL, self.PASL],
                    case_insensitive=True)),
                self.KEY_LABEL_DURATION:
                Parameter(validators=[
                    range_inclusive_validator(0, 100),
                    isinstance_validator(float),
                ]),
                self.KEY_SIGNAL_TIME:
                Parameter(validators=[
                    range_inclusive_validator(0, 100),
                    isinstance_validator(float),
                ]),
                self.KEY_LABEL_EFFICIENCY:
                Parameter(validators=[
                    range_inclusive_validator(0, 1),
                    isinstance_validator(float),
                ]),
                self.KEY_LAMBDA_BLOOD_BRAIN:
                Parameter(validators=[
                    range_inclusive_validator(0, 1),
                    isinstance_validator(float),
                ]),
                self.KEY_T1_ARTERIAL_BLOOD:
                Parameter(validators=[
                    range_inclusive_validator(0, 100),
                    isinstance_validator(float),
                ]),
            })

        input_validator.validate(self.inputs,
                                 error_type=FilterInputValidationError)

        # Check that all the input images are all the same dimensions
        input_keys = self.inputs.keys()
        keys_of_images = [
            key for key in input_keys
            if isinstance(self.inputs[key], BaseImageContainer)
        ]

        list_of_image_shapes = [
            self.inputs[key].shape for key in keys_of_images
        ]
        if list_of_image_shapes.count(
                list_of_image_shapes[0]) != len(list_of_image_shapes):
            raise FilterInputValidationError([
                "Input image shapes do not match.",
                [
                    f"{keys_of_images[i]}: {list_of_image_shapes[i]}, "
                    for i in range(len(list_of_image_shapes))
                ],
            ])
Пример #16
0
    def _validate_inputs(self):
        """ Checks that the inputs meet their validation criteria

        `'rotation'` (optional) must be a Tuple of floats of length 3, each value -180 to 180
        inclusive,default (optional) = (0.0, 0.0, 0.0)
        `'rotation_origin'` (optional) must be a Tuple of floats of length 3,
        default = (0.0, 0.0, 0.0)
        `'translation'` (optional) must be a Tuple of floats of length 3, default = (0.0, 0.0, 0.0)
        `'scale'` (optional) must be a Tuple of floats of length 3, default = (1.0, 1.0, 1.0)
        `'affine'` (optional) must be a numpy.ndarray of shape (4,4), default = numpy.eye(4)
        """

        input_validator = ParameterValidator(
            parameters={
                self.KEY_ROTATION:
                Parameter(
                    validators=[
                        isinstance_validator(tuple),
                        for_each_validator(isinstance_validator(float)),
                        for_each_validator(range_inclusive_validator(
                            -180, 180)),
                    ],
                    optional=True,
                    default_value=(0.0, 0.0, 0.0),
                ),
                self.KEY_ROTATION_ORIGIN:
                Parameter(
                    validators=[
                        isinstance_validator(tuple),
                        for_each_validator(isinstance_validator(float)),
                    ],
                    optional=True,
                    default_value=(0.0, 0.0, 0.0),
                ),
                self.KEY_TRANSLATION:
                Parameter(
                    validators=[
                        isinstance_validator(tuple),
                        for_each_validator(isinstance_validator(float)),
                    ],
                    optional=True,
                    default_value=(0.0, 0.0, 0.0),
                ),
                self.KEY_SCALE:
                Parameter(
                    validators=[
                        isinstance_validator(tuple),
                        for_each_validator(isinstance_validator(float)),
                    ],
                    optional=True,
                    default_value=(1.0, 1.0, 1.0),
                ),
                self.KEY_AFFINE:
                Parameter(
                    validators=[isinstance_validator(np.ndarray)],
                    optional=True,
                    default_value=np.eye(4),
                ),
                self.KEY_AFFINE_LAST:
                Parameter(
                    validators=[isinstance_validator(np.ndarray)],
                    optional=True,
                    default_value=np.eye(4),
                ),
            })

        # validate, returning a dictionary which also includes default parameters
        new_params = input_validator.validate(
            self.inputs, error_type=FilterInputValidationError)

        # Further validation that can't be handled by the parameter validator
        # Check that AffineMatrixFilter.KEY_AFFINE is of size 4x4
        if new_params[self.KEY_AFFINE].shape != (4, 4):
            raise FilterInputValidationError
        # Check that AffineMatrixFilter.KEY_AFFINE_LAST is of size 4x4
        if new_params[self.KEY_AFFINE_LAST].shape != (4, 4):
            raise FilterInputValidationError

        # Check that the tuple AffineMatrixFilter.KEY_ROTATION's length is 3
        if len(new_params[self.KEY_ROTATION]) != 3:
            raise FilterInputValidationError

        # Check that the tuple AffineMatrixFilter.KEY_ROTATION_ORIGIN's length is 3
        if len(new_params[self.KEY_ROTATION_ORIGIN]) != 3:
            raise FilterInputValidationError

        # Check that the tuple AffineMatrixFilter.KEY_TRANSLATION's length is 3
        if len(new_params[self.KEY_TRANSLATION]) != 3:
            raise FilterInputValidationError

        # Check that the tuple AffineMatrixFilter.KEY_SCALE's length is 3
        if len(new_params[self.KEY_SCALE]) != 3:
            raise FilterInputValidationError

        # merge the updated parameters from the output with the input parameters
        self.inputs = {**self._i, **new_params}
    def _validate_inputs(self):
        """ Checks that the inputs meet their validation critera
        't1' must be derived from BaseImageContainer, >=0, and non-complex
        't2' must be derived from BaseImageContainer, >=0, and non-complex
        't2_star' must be derived from BaseImageContainer, >=0, and non-complex
            Only required if 'acq_contrast' == 'ge'
        'm0' must be derived from BaseImageContainer, >=0, and non-complex
        'mag_enc' (optional) must be derived from BaseImageContainer and non-complex
        'acq_contrast' must be a string and equal to "ge" or "se" (case insensitive)
        'echo_time' must be a float and >= 0
        'repetition_time' must be a float and >= 0
        'excitation_flip_angle' must be a float and >=0
        'inversion_flip_angle' must be a float and >=0
        'inversion_time' must be a float and >=0

        All images must have the same dimensions

        """
        input_validator = ParameterValidator(
            parameters={
                self.KEY_M0:
                Parameter(validators=[
                    isinstance_validator(BaseImageContainer),
                    greater_than_equal_to_validator(0),
                ]),
                self.KEY_T1:
                Parameter(validators=[
                    isinstance_validator(BaseImageContainer),
                    greater_than_equal_to_validator(0),
                ]),
                self.KEY_T2:
                Parameter(validators=[
                    isinstance_validator(BaseImageContainer),
                    greater_than_equal_to_validator(0),
                ]),
                self.KEY_T2_STAR:
                Parameter(
                    validators=[
                        isinstance_validator(BaseImageContainer),
                        greater_than_equal_to_validator(0),
                    ],
                    optional=True,
                ),
                self.KEY_MAG_ENC:
                Parameter(
                    validators=[isinstance_validator(BaseImageContainer)],
                    optional=True),
                self.KEY_ACQ_CONTRAST:
                Parameter(validators=[
                    isinstance_validator(str),
                    from_list_validator(
                        [self.CONTRAST_GE, self.CONTRAST_SE, self.CONTRAST_IR],
                        case_insensitive=True,
                    ),
                ]),
                self.KEY_ECHO_TIME:
                Parameter(validators=[
                    isinstance_validator(float),
                    greater_than_equal_to_validator(0),
                ]),
                self.KEY_REPETITION_TIME:
                Parameter(validators=[
                    isinstance_validator(float),
                    greater_than_equal_to_validator(0),
                ]),
                self.KEY_EXCITATION_FLIP_ANGLE:
                Parameter(
                    validators=[
                        isinstance_validator(float),
                    ],
                    optional=True,
                ),
                self.KEY_INVERSION_FLIP_ANGLE:
                Parameter(
                    validators=[
                        isinstance_validator(float),
                    ],
                    optional=True,
                ),
                self.KEY_INVERSION_TIME:
                Parameter(
                    validators=[
                        isinstance_validator(float),
                        greater_than_equal_to_validator(0),
                    ],
                    optional=True,
                ),
                self.KEY_IMAGE_FLAVOUR:
                Parameter(validators=[
                    isinstance_validator(str),
                ],
                          optional=True),
            })
        input_validator.validate(self.inputs,
                                 error_type=FilterInputValidationError)

        # Parameters that are conditionally required based on the value of "acq_contrast"
        # if the acquisition contrast is gradient echo ("ge")
        if self.inputs[self.KEY_ACQ_CONTRAST].lower() == self.CONTRAST_GE:
            # 't2_star' must be present in inputs
            if self.inputs.get(self.KEY_T2_STAR) is None:
                raise FilterInputValidationError(
                    "Acquisition contrast is ge, 't2_star' image required")
        # if the acquisition contrast is gradient echo ("ge") or inversion recovery ("ir")
        if self.inputs[self.KEY_ACQ_CONTRAST].lower() in (
                self.CONTRAST_GE,
                self.CONTRAST_IR,
        ):
            # 'excitation_flip_angle' must be present in inputs
            if self.inputs.get(self.KEY_EXCITATION_FLIP_ANGLE) is None:
                raise FilterInputValidationError(
                    f"Acquisition contrast is {self.inputs[self.KEY_ACQ_CONTRAST]},"
                    " 'excitation_flip_angle' required")

        # if the acquisition contrast is inversion recovery ("ir")
        if self.inputs[self.KEY_ACQ_CONTRAST].lower() == self.CONTRAST_IR:
            if self.inputs.get(self.KEY_INVERSION_FLIP_ANGLE) is None:
                raise FilterInputValidationError(
                    f"Acquisition contrast is {self.inputs[self.KEY_ACQ_CONTRAST]},"
                    " 'inversion_flip_angle' required")
            if self.inputs.get(self.KEY_INVERSION_TIME) is None:
                raise FilterInputValidationError(
                    f"Acquisition contrast is {self.inputs[self.KEY_ACQ_CONTRAST]},"
                    " 'inversion_time' required")
            if self.inputs.get(self.KEY_REPETITION_TIME) < (
                    self.inputs.get(self.KEY_ECHO_TIME) +
                    self.inputs.get(self.KEY_INVERSION_TIME)):
                raise FilterInputValidationError(
                    "repetition_time must be greater than echo_time + inversion_time"
                )

        # Check repetition_time is not < echo_time for ge and se
        if self.inputs.get(self.KEY_REPETITION_TIME) < self.inputs.get(
                self.KEY_ECHO_TIME):
            raise FilterInputValidationError(
                "repetition_time must be greater than echo_time")

        # Check that all the input images are all the same dimensions
        input_keys = self.inputs.keys()
        keys_of_images = [
            key for key in input_keys
            if isinstance(self.inputs[key], BaseImageContainer)
        ]

        list_of_image_shapes = [
            self.inputs[key].shape for key in keys_of_images
        ]
        if list_of_image_shapes.count(
                list_of_image_shapes[0]) != len(list_of_image_shapes):
            raise FilterInputValidationError([
                "Input image shapes do not match.",
                [
                    f"{keys_of_images[i]}: {list_of_image_shapes[i]}, "
                    for i in range(len(list_of_image_shapes))
                ],
            ])

        # Check that all the input images are not of image_type == "COMPLEX_IMAGE_TYPE"
        for key in keys_of_images:
            if self.inputs[key].image_type == COMPLEX_IMAGE_TYPE:
                raise FilterInputValidationError(
                    f"{key} has image type {COMPLEX_IMAGE_TYPE}, this is not supported"
                )
Пример #18
0
    def _validate_inputs(self):
        """ Checks that the inputs meet their validation critera
        'image' must be a derived from BaseImageContainer
        'output_directory' must be a string and a path
        'filename_prefix' must be a string and is optional

        Also checks the input image's metadata
        """

        input_validator = ParameterValidator(
            parameters={
                self.KEY_IMAGE:
                Parameter(validators=isinstance_validator(BaseImageContainer)),
                self.KEY_OUTPUT_DIRECTORY:
                Parameter(validators=isinstance_validator(str)),
                self.KEY_FILENAME_PREFIX:
                Parameter(
                    validators=isinstance_validator(str),
                    optional=True,
                    default_value="",
                ),
            })
        # validate the inputs
        new_params = input_validator.validate(
            self.inputs, error_type=FilterInputValidationError)

        metdata_validator = ParameterValidator(
            parameters={
                self.SERIES_TYPE:
                Parameter(
                    validators=from_list_validator(SUPPORTED_IMAGE_TYPES)),
                MODALITY:
                Parameter(validators=isinstance_validator(str), optional=True),
                self.SERIES_NUMBER:
                Parameter(validators=[
                    isinstance_validator(int),
                    greater_than_equal_to_validator(0),
                ]),
                ASL_CONTEXT:
                Parameter(
                    validators=isinstance_validator((str, list)),
                    optional=True,
                ),
                GkmFilter.KEY_LABEL_TYPE:
                Parameter(
                    validators=isinstance_validator(str),
                    optional=True,
                ),
                GkmFilter.KEY_LABEL_DURATION:
                Parameter(validators=isinstance_validator(float),
                          optional=True),
                GkmFilter.KEY_POST_LABEL_DELAY:
                Parameter(validators=isinstance_validator(float),
                          optional=True),
                GkmFilter.KEY_LABEL_EFFICIENCY:
                Parameter(validators=isinstance_validator(float),
                          optional=True),
                GroundTruthLoaderFilter.KEY_QUANTITY:
                Parameter(
                    validators=isinstance_validator(str),
                    optional=True,
                ),
                GroundTruthLoaderFilter.KEY_UNITS:
                Parameter(
                    validators=isinstance_validator(str),
                    optional=True,
                ),
                "image_flavour":
                Parameter(
                    validators=isinstance_validator(str),
                    optional=True,
                ),
            })
        # validate the metadata
        metadata = self.inputs[self.KEY_IMAGE].metadata
        metdata_validator.validate(metadata,
                                   error_type=FilterInputValidationError)

        # Specific validation for series_type == "structural"
        if metadata[self.SERIES_TYPE] == STRUCTURAL:
            if metadata.get(MODALITY) is None:
                raise FilterInputValidationError(
                    "metadata field 'modality' is required when `series_type` is 'structural'"
                )

        # specific validation when series_type is "ground_truth"
        if metadata[self.SERIES_TYPE] == GROUND_TRUTH:
            if metadata.get(GroundTruthLoaderFilter.KEY_QUANTITY) is None:
                raise FilterInputValidationError(
                    "metadata field 'quantity' is required when `series_type` is 'ground_truth'"
                )
        if metadata[self.SERIES_TYPE] == GROUND_TRUTH:
            if metadata.get(GroundTruthLoaderFilter.KEY_UNITS) is None:
                raise FilterInputValidationError(
                    "metadata field 'units' is required when `series_type` is 'ground_truth'"
                )

        # Specific validation for series_type == "asl"
        if metadata[self.SERIES_TYPE] == ASL:
            # asl_context needs some further validating
            asl_context = metadata.get(ASL_CONTEXT)
            if asl_context is None:
                raise FilterInputValidationError(
                    "metadata field 'asl_context' is required when `series_type` is 'asl'"
                )
            if isinstance(asl_context, str):
                asl_context_validator = ParameterValidator(
                    parameters={
                        ASL_CONTEXT:
                        Parameter(validators=from_list_validator(
                            SUPPORTED_ASL_CONTEXTS), ),
                    })

            elif isinstance(asl_context, list):
                asl_context_validator = ParameterValidator(
                    parameters={
                        ASL_CONTEXT:
                        Parameter(validators=for_each_validator(
                            from_list_validator(SUPPORTED_ASL_CONTEXTS)), ),
                    })
            asl_context_validator.validate(
                {"asl_context": asl_context},
                error_type=FilterInputValidationError)

            # determine the modality_label based on asl_context
            modality_label = self.determine_asl_modality_label(asl_context)

            if modality_label == ASL:
                # do some checking for when the `modality` is 'asl'
                if metadata.get(GkmFilter.KEY_LABEL_TYPE) is None:
                    raise FilterInputValidationError(
                        "metadata field 'label_type' is required for 'series_type'"
                        + " and 'modality' is 'asl'")
                if metadata.get(GkmFilter.KEY_LABEL_DURATION) is None:
                    raise FilterInputValidationError(
                        "metadata field 'label_duration' is required for 'series_type'"
                        + " and 'modality' is 'asl'")
                if metadata.get(GkmFilter.KEY_POST_LABEL_DELAY) is None:
                    raise FilterInputValidationError(
                        "metadata field 'post_label_delay' is required for 'series_type'"
                        + " and 'modality' is 'asl'")
                if metadata.get("image_flavour") is None:
                    raise FilterInputValidationError(
                        "metadata field 'image_flavour' is required for 'series_type'"
                        + " and 'modality' is 'asl'")

        # Check that self.inputs[self.KEY_OUTPUT_DIRECTORY] is a valid path.
        if not os.path.exists(self.inputs[self.KEY_OUTPUT_DIRECTORY]):
            raise FilterInputValidationError(
                f"'output_directory' {self.inputs[self.KEY_OUTPUT_DIRECTORY]} does not exist"
            )

        # merge the updated parameters from the output with the input parameters
        self.inputs = {**self._i, **new_params}
    def _validate_inputs(self):
        """Checks that the inputs meet their validation criteria
        `'object'` must be derived from BaseImageContainer
        `'target_shape'` (optional)must be a Tuple of ints of length 3, values > 0
        `'rotation'` (optional) must be a Tuple of floats of length 3, each value -180 to 180
        inclusive, default (optional) = (0.0, 0.0, 0.0)
        `'rotation_origin'` (optional) must be a Tuple of floats of length 3,
        default = (0.0, 0.0, 0.0)
        `'translation'` (optional) must be a Tuple of floats of length 3, default = (0.0, 0.0, 0.0)
        """

        input_validator = ParameterValidator(
            parameters={
                self.KEY_IMAGE:
                Parameter(validators=isinstance_validator(BaseImageContainer)),
                self.KEY_ROTATION:
                Parameter(
                    validators=[
                        isinstance_validator(tuple),
                        for_each_validator(isinstance_validator(float)),
                        for_each_validator(range_inclusive_validator(
                            -180, 180)),
                    ],
                    optional=True,
                    default_value=(0.0, 0.0, 0.0),
                ),
                self.KEY_ROTATION_ORIGIN:
                Parameter(
                    validators=[
                        isinstance_validator(tuple),
                        for_each_validator(isinstance_validator(float)),
                    ],
                    optional=True,
                    default_value=(0.0, 0.0, 0.0),
                ),
                self.KEY_TRANSLATION:
                Parameter(
                    validators=[
                        isinstance_validator(tuple),
                        for_each_validator(isinstance_validator(float)),
                    ],
                    optional=True,
                    default_value=(0.0, 0.0, 0.0),
                ),
                self.KEY_TARGET_SHAPE:
                Parameter(
                    validators=[
                        isinstance_validator(tuple),
                        for_each_validator(isinstance_validator(int)),
                        for_each_validator(greater_than_validator(0)),
                    ],
                    optional=True,
                    default_value=(9999, 9999, 9999),
                ),
            })

        # validate, returning a dictionary which also includes default parameters
        new_params = input_validator.validate(
            self.inputs, error_type=FilterInputValidationError)

        # Further validation that can't be handled by the parameter validator

        if new_params[self.KEY_TARGET_SHAPE] == (9999, 9999, 9999):
            new_params[self.KEY_TARGET_SHAPE] = self.inputs[
                self.KEY_IMAGE].shape

        # Check that the tuple self.KEY_ROTATION's length is 3
        if len(new_params[self.KEY_ROTATION]) != 3:
            raise FilterInputValidationError

        # Check that the tuple self.KEY_ROTATION_ORIGIN's length is 3
        if len(new_params[self.KEY_ROTATION_ORIGIN]) != 3:
            raise FilterInputValidationError

        # Check that the tuple self.KEY_TRANSLATION's length is 3
        if len(new_params[self.KEY_TRANSLATION]) != 3:
            raise FilterInputValidationError

        # Check that the tuple self.KEY_SCALE's length is 3
        if len(new_params[self.KEY_TARGET_SHAPE]) != 3:
            raise FilterInputValidationError

        # merge the updated parameters from the output with the input parameters
        self.inputs = {**self._i, **new_params}
Пример #20
0
 def _validate_inputs(self):
     """
     Checks that the inputs meet their validation criteria
     Note that values are only checked if they are present and the correct
     type, as more rigorous checking is performed in each corresponding filter.
     't1': BaseImageContainer
     't2': BaseImageContainer
     't2_star': BaseImageContainer
     'm0': BaseImageContainer
     'mag_enc': BaseImageContainer, optional
     'acq_contrast': str
     'echo_time': float
     'repetition_time': float
     'excitation_flip_angle': float, optional
     'inversion_flip_angle': float, optional
     'inversion_time': float, optional
     'image_flavour': str, optional
     'target_shape': Tuple[int, int, int], optional
     'rotation': Tuple[float, float, float], optional
     'rotation_origin': Tuple[float, float, float], optional
     'translation': Tuple[float, float, float], optional
     'reference_image': BaseImageContainer, optional
     'snr': float
     """
     input_validator = ParameterValidator(
         parameters={
             self.KEY_M0: Parameter(
                 validators=[
                     isinstance_validator(BaseImageContainer),
                 ]
             ),
             self.KEY_T1: Parameter(
                 validators=[
                     isinstance_validator(BaseImageContainer),
                 ]
             ),
             self.KEY_T2: Parameter(
                 validators=[
                     isinstance_validator(BaseImageContainer),
                 ]
             ),
             self.KEY_T2_STAR: Parameter(
                 validators=[
                     isinstance_validator(BaseImageContainer),
                 ],
             ),
             self.KEY_MAG_ENC: Parameter(
                 validators=[isinstance_validator(BaseImageContainer)], optional=True
             ),
             self.KEY_ACQ_CONTRAST: Parameter(
                 validators=[
                     isinstance_validator(str),
                 ]
             ),
             self.KEY_ECHO_TIME: Parameter(
                 validators=[
                     isinstance_validator(float),
                 ]
             ),
             self.KEY_REPETITION_TIME: Parameter(
                 validators=[
                     isinstance_validator(float),
                 ]
             ),
             self.KEY_EXCITATION_FLIP_ANGLE: Parameter(
                 validators=[
                     isinstance_validator(float),
                 ],
             ),
             self.KEY_INVERSION_FLIP_ANGLE: Parameter(
                 validators=[
                     isinstance_validator(float),
                 ],
                 optional=True,
             ),
             self.KEY_INVERSION_TIME: Parameter(
                 validators=[
                     isinstance_validator(float),
                 ],
                 optional=True,
             ),
             self.KEY_IMAGE_FLAVOUR: Parameter(
                 validators=[
                     isinstance_validator(str),
                 ],
                 optional=True,
             ),
             self.KEY_TARGET_SHAPE: Parameter(
                 validators=[
                     isinstance_validator(tuple),
                 ],
                 optional=True,
             ),
             self.KEY_ROTATION: Parameter(
                 validators=[
                     isinstance_validator(tuple),
                 ],
                 optional=True,
             ),
             self.KEY_ROTATION_ORIGIN: Parameter(
                 validators=[
                     isinstance_validator(tuple),
                 ],
                 optional=True,
             ),
             self.KEY_TRANSLATION: Parameter(
                 validators=[
                     isinstance_validator(tuple),
                 ],
                 optional=True,
             ),
             self.KEY_REF_IMAGE: Parameter(
                 validators=[isinstance_validator(BaseImageContainer)], optional=True
             ),
             self.KEY_SNR: Parameter(
                 validators=[
                     isinstance_validator(float),
                 ]
             ),
         }
     )
     input_validator.validate(self.inputs, error_type=FilterInputValidationError)
Пример #21
0
 GROUND_TRUTH:
 ParameterValidator(
     parameters={
         ROT_X:
         Parameter(validators=range_inclusive_validator(-180.0, 180.0),
                   default_value=0.0),
         ROT_Y:
         Parameter(validators=range_inclusive_validator(-180.0, 180.0),
                   default_value=0.0),
         ROT_Z:
         Parameter(validators=range_inclusive_validator(-180.0, 180.0),
                   default_value=0.0),
         TRANSL_X:
         Parameter(validators=range_inclusive_validator(-1000.0, 1000.0),
                   default_value=0.0),
         TRANSL_Y:
         Parameter(validators=range_inclusive_validator(-1000.0, 1000.0),
                   default_value=0.0),
         TRANSL_Z:
         Parameter(validators=range_inclusive_validator(-1000.0, 1000.0),
                   default_value=0.0),
         ACQ_MATRIX:
         Parameter(
             validators=[
                 list_of_type_validator(int),
                 of_length_validator(3),
                 for_each_validator(greater_than_validator(0)),
             ],
             default_value=[64, 64, 12],
         ),
     }),
 STRUCTURAL: