Skip to content

Data Validators

Aggregated and individual rule validators.

BaseRuleValidator

BaseRuleValidator(configuration, feedback)

Validator for an individual rule.

This is an abstract class that needs to be subclassed with the specific validation implementation by overriding the validate protected function.

Source code in src/cplus_plugin/lib/validation/validators.py
def __init__(self, configuration: RuleConfiguration, feedback: ValidationFeedback):
    self._config = configuration
    self._feedback = feedback
    self._result: RuleResult = None
    self.model_components: typing.List[LayerModelComponent] = list()

feedback property

feedback

Returns the feedback object used in the validator for providing feedback on the validation process.

Returns:

Type Description
ValidationFeedback

Feedback object used in the validator for providing feedback on the validation process.

result property

result

Returns the result of the validation process.

Returns:

Type Description
RuleResult

Result of the validation process.

rule_configuration property

rule_configuration

Returns the rule configuration use in the validator.

Returns:

Type Description
RuleConfiguration

Rule configuration used in the validator.

rule_type abstractmethod property

rule_type

Returns the type identifier of the rule validator.

Returns:

Type Description
RuleType

Type identifier of the rule validator.

get_default_layer_metadata

get_default_layer_metadata(layer_uuid, layer_type='ncs_pathway')

Get default layer metadata

Parameters:

Name Type Description Default
layer_uuid str

UUID of the layer

required
layer_type str

Type of the layer e.g. ncs_pathway

'ncs_pathway'

Returns:

Type Description
typing.Dict

Layer metadata

Source code in src/cplus_plugin/lib/validation/validators.py
def get_default_layer_metadata(
    self, layer_uuid: str, layer_type: str = "ncs_pathway"
) -> typing.Dict:
    """Get default layer metadata

    :param layer_uuid: UUID of the layer
    :type layer_uuid: str

    :param layer_type: Type of the layer e.g. ncs_pathway
    :type layer_type: str

    :return: Layer metadata
    :rtype: typing.Dict
    """
    layers = settings_manager.get_default_layers(layer_type, as_dict=True)
    layer = layers.get(layer_uuid)
    layer_metadata = layer.get("metadata", {})
    return layer_metadata

is_comparative

is_comparative()

Indicate whether the validation check is comparative i.e. relative to the datasets or an absolute check. The former requires more than one dataset to execute the validation whereas the latter can be executed even for one dataset.

Returns:

Type Description
bool

True if the validator is comparative else False. Default is True.

Source code in src/cplus_plugin/lib/validation/validators.py
def is_comparative(self) -> bool:
    """Indicate whether the validation check is comparative i.e. relative to
    the datasets or an absolute check. The former requires more than one
    dataset to execute the validation whereas the latter can be executed
    even for one dataset.

    :returns: True if the validator is comparative else False. Default is
    True.
    :rtype: bool
    """
    return True

log

log(message, info=True)

Convenience function that logs the given messages by appending the information in the rule configuration.

Parameters:

Name Type Description Default
message str

Message to be logged.

required
info bool

False if the message should be logged as a warning else True if information.

True
Source code in src/cplus_plugin/lib/validation/validators.py
def log(self, message: str, info: bool = True):
    """Convenience function that logs the given messages by appending
    the information in the rule configuration.

    :param message: Message to be logged.
    :type message: str

    :param info: False if the message should be logged as a warning
    else True if information.
    :type info: bool
    """
    msg = f"{self._config.rule_name} - {message}"
    log(message=msg, info=info)

run

run()

Initiates the rule validation process and returns a result indicating whether the process succeeded or failed.

A fail result would, for instance, be due to no layers, or only one layer, defined for validation.

Returns:

Type Description
bool

True if the validation process succeeded or False if it failed.

Source code in src/cplus_plugin/lib/validation/validators.py
def run(self) -> bool:
    """Initiates the rule validation process and returns
    a result indicating whether the process succeeded or
    failed.

    A fail result would, for instance, be due to no layers,
    or only one layer, defined for validation.

    :returns: True if the validation process succeeded
    or False if it failed.
    :rtype: bool
    """
    if len(self.model_components) == 0:
        msg = tr("No datasets for validation.")
        self.log(msg, False)

        return False

    return self._validate()

CarbonLayerResolutionValidator

CarbonLayerResolutionValidator(configuration, feedback)

Bases: ResolutionValidator

Checks if the resolution of the carbon layers matches that of the corresponding NCS pathways.

Source code in src/cplus_plugin/lib/validation/validators.py
def __init__(self, configuration: RuleConfiguration, feedback: ValidationFeedback):
    self._config = configuration
    self._feedback = feedback
    self._result: RuleResult = None
    self.model_components: typing.List[LayerModelComponent] = list()

rule_type property

rule_type

Returns the no data value rule validator.

Returns:

Type Description
RuleType

No data value rule validator.

is_comparative

is_comparative()

Validator can be used for even one dataset.

Source code in src/cplus_plugin/lib/validation/validators.py
def is_comparative(self) -> bool:
    """Validator can be used for even one dataset."""
    return False

CrsValidator

CrsValidator(configuration, feedback)

Bases: BaseRuleValidator

Checks if the input datasets have the same CRS.

Source code in src/cplus_plugin/lib/validation/validators.py
def __init__(self, configuration: RuleConfiguration, feedback: ValidationFeedback):
    self._config = configuration
    self._feedback = feedback
    self._result: RuleResult = None
    self.model_components: typing.List[LayerModelComponent] = list()

rule_type property

rule_type

Returns the CRS rule validator.

Returns:

Type Description
RuleType

CRS rule validator.

DataValidator

DataValidator(model_components=None)

Bases: QgsTask

Abstract runner for checking a set of datasets against specific validation rules.

Rule validators need to be added manually in the sub-class implementation and set the model component type of the result.

Source code in src/cplus_plugin/lib/validation/validators.py
def __init__(self, model_components=None):
    super().__init__(tr(self.NAME))

    self.model_components = []
    if model_components is not None:
        self.model_components = model_components

    self._result: ValidationResult = None
    self._rule_validators = []
    self._applicable_rule_validators = []
    self._feedback = ValidationFeedback()
    self._feedback.rule_progress_changed.connect(self._on_rule_progress_changed)
    self._feedback.rule_validation_completed.connect(
        self._on_rule_validation_completed
    )

    # Used to calculate the overall progress
    self._rule_reference_progress = 0

feedback property

feedback

Returns the feedback object used in the validator for providing feedback on the validation process.

Returns:

Type Description
ValidationFeedback

Feedback object used in the validator for providing feedback on the validation process.

result property

result

Returns the result of the validation process.

Returns:

Type Description
ValidationResult

Result of the validation process.

add_rule_validator

add_rule_validator(rule_validator)

Add a rule validator for validating the input model components.

Parameters:

Name Type Description Default
rule_validator BaseRuleValidator

Validator for checking the input model components based on the specific validation rule.

required
Source code in src/cplus_plugin/lib/validation/validators.py
def add_rule_validator(self, rule_validator: BaseRuleValidator):
    """Add a rule validator for validating the input model components.

    :param rule_validator: Validator for checking the input model
    components based on the specific validation rule.
    :type rule_validator: BaseRuleValidator
    """
    self._rule_validators.append(rule_validator)

cancel

cancel()

Cancel the validation process.

Source code in src/cplus_plugin/lib/validation/validators.py
def cancel(self):
    """Cancel the validation process."""
    self.log(tr("Validation process has been cancelled."))

    self._feedback.cancel()

    super().cancel()

create_rule_validator staticmethod

create_rule_validator(rule_type, config, feedback)

Factory method for creating a rule validator object.

Parameters:

Name Type Description Default
rule_type RuleType

The type of the validator rule.

required
config RuleConfiguration

The context information for configuring the rule validator.

required
feedback ValidationFeedback

Feedback object for reporting progress.

required

Returns:

Type Description
BaseRuleValidator

An instance of the specific rule validator.

Source code in src/cplus_plugin/lib/validation/validators.py
@staticmethod
def create_rule_validator(
    rule_type: RuleType, config: RuleConfiguration, feedback: ValidationFeedback
) -> BaseRuleValidator:
    """Factory method for creating a rule validator object.

    :param rule_type: The type of the validator rule.
    :type rule_type: RuleType

    :param config: The context information for configuring
    the rule validator.
    :type rule_type: RuleConfiguration

    :param feedback: Feedback object for reporting progress.
    :type feedback: ValidationFeedback

    :returns: An instance of the specific rule validator.
    :rtype: BaseRuleValidator
    """
    validator_cls = DataValidator.validator_cls_by_type(rule_type)

    return validator_cls(config, feedback)

finished

finished(result)

Depending on the outcome of the validation process, validation_completed signal will be emitted only if the validation was successful. The result attribute will also contain the validation result object. If an error occurred during the validation process, the validation result object will be None.

Parameters:

Name Type Description Default
result bool

True if the validation process was successful, else False.

required
Source code in src/cplus_plugin/lib/validation/validators.py
def finished(self, result: bool):
    """Depending on the outcome of the validation process,
    `validation_completed` signal will be emitted only if the
    validation was successful. The `result` attribute will also contain the
    validation result object. If an error occurred during the validation
    process, the validation result object will be None.

    :param result: True if the validation process was successful, else False.
    :type result: bool
    """
    if result:
        rule_results = [
            rule_validator.result
            for rule_validator in self._applicable_rule_validators
        ]
        self._result = ValidationResult(rule_results, self.MODEL_COMPONENT_TYPE)
        self._feedback.validation_completed.emit(self._result)
        self.log("Validation complete.")

log

log(message, info=True)

Convenience function that logs the given messages by appending the information for the validator.

Parameters:

Name Type Description Default
message str

Message to be logged.

required
info bool

False if the message should be logged as a warning else True if information.

True
Source code in src/cplus_plugin/lib/validation/validators.py
def log(self, message: str, info: bool = True):
    """Convenience function that logs the given messages by appending
    the information for the validator.

    :param message: Message to be logged.
    :type message: str

    :param info: False if the message should be logged as a warning
    else True if information.
    :type info: bool
    """
    msg = f"{self.NAME} - {message}"
    log(message=msg, info=info)

rule_validators staticmethod

rule_validators()

Returns all the rule validator classes, any new validator type needs to be added here.

The validator classes are indexed by their corresponding rule type enum.

Returns:

Type Description
dict

Collection containing rule validator classes indexed by their corresponding rule types.

Source code in src/cplus_plugin/lib/validation/validators.py
@staticmethod
def rule_validators() -> typing.Dict[RuleType, typing.Type[BaseRuleValidator]]:
    """Returns all the rule validator classes, any new validator
    type needs to be added here.

    The validator classes are indexed by their corresponding rule
    type enum.

    :returns: Collection containing rule validator classes indexed
    by their corresponding rule types.
    :rtype: dict
    """
    return {
        RuleType.DATA_TYPE: RasterValidator,
        RuleType.CRS: CrsValidator,
        RuleType.NO_DATA_VALUE: NoDataValueValidator,
        RuleType.RESOLUTION: ResolutionValidator,
        RuleType.CARBON_RESOLUTION: CarbonLayerResolutionValidator,
        RuleType.PROJECTED_CRS: ProjectedCrsValidator,
    }

run

run()

Initiates the validation process based on the specified validators and returns a result indicating whether the process succeeded or failed.

Returns:

Type Description
bool

True if the validation process succeeded or False if it failed.

Source code in src/cplus_plugin/lib/validation/validators.py
def run(self) -> bool:
    """Initiates the validation process based on the
    specified validators and returns a result indicating
    whether the process succeeded or failed.

    :returns: True if the validation process succeeded
    or False if it failed.
    :rtype: bool
    """
    if len(self._rule_validators) == 0:
        msg = tr("No rule validators specified.")
        self.log(msg, False)

        return False

    if len(self.model_components) == 0:
        msg = tr("At least one dataset is required for the validation process.")
        self.log(msg, False)

        return False

    status = True

    try:
        status = self._validate()
    except Exception as ex:
        exc_info = "".join(traceback.TracebackException.from_exception(ex).format())
        self.log(exc_info, False)
        status = False

    return status

validator_cls_by_type staticmethod

validator_cls_by_type(rule_type)

Gets the rule validator class based on the corresponding rule type.

Parameters:

Name Type Description Default
rule_type RuleType

The type of the validator rule.

required

Returns:

Type Description
BaseRuleValidator

The rule validator class corresponding to the given rule type.

Source code in src/cplus_plugin/lib/validation/validators.py
@staticmethod
def validator_cls_by_type(rule_type: RuleType) -> typing.Type[BaseRuleValidator]:
    """Gets the rule validator class based on the corresponding rule type.

    :param rule_type: The type of the validator rule.
    :type rule_type: RuleType

    :returns: The rule validator class corresponding to the
    given rule type.
    :rtype: BaseRuleValidator
    """
    return DataValidator.rule_validators()[rule_type]

NcsDataValidator

NcsDataValidator(*args, **kwargs)

Bases: DataValidator

Validates both NCS pathway and carbon layer datasets. The resolution check for carbon layers is tagged as a warning rather than an error.

Source code in src/cplus_plugin/lib/validation/validators.py
def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.model_components = kwargs.pop("ncs_pathways", list)
    self._initialize_rule_validators()

NoDataValueValidator

NoDataValueValidator(configuration, feedback)

Bases: BaseRuleValidator

Checks if applicable input datasets have the same no data value.

Source code in src/cplus_plugin/lib/validation/validators.py
def __init__(self, configuration: RuleConfiguration, feedback: ValidationFeedback):
    self._config = configuration
    self._feedback = feedback
    self._result: RuleResult = None
    self.model_components: typing.List[LayerModelComponent] = list()

rule_type property

rule_type

Returns the no data value rule validator.

Returns:

Type Description
RuleType

No data value rule validator.

is_comparative

is_comparative()

Validator can be used for even one dataset.

Source code in src/cplus_plugin/lib/validation/validators.py
def is_comparative(self) -> bool:
    """Validator can be used for even one dataset."""
    return False

ProjectedCrsValidator

ProjectedCrsValidator(configuration, feedback)

Bases: BaseRuleValidator

Checks if the input datasets have a projected CRS.

Source code in src/cplus_plugin/lib/validation/validators.py
def __init__(self, configuration: RuleConfiguration, feedback: ValidationFeedback):
    self._config = configuration
    self._feedback = feedback
    self._result: RuleResult = None
    self.model_components: typing.List[LayerModelComponent] = list()

rule_type property

rule_type

Returns the projected CRS rule validator.

Returns:

Type Description
RuleType

Projected CRS rule validator.

is_comparative

is_comparative()

Validator can be used for even one dataset.

Source code in src/cplus_plugin/lib/validation/validators.py
def is_comparative(self) -> bool:
    """Validator can be used for even one dataset."""
    return False

RasterValidator

RasterValidator(configuration, feedback)

Bases: BaseRuleValidator

Checks if the input datasets are raster layers.

Source code in src/cplus_plugin/lib/validation/validators.py
def __init__(self, configuration: RuleConfiguration, feedback: ValidationFeedback):
    self._config = configuration
    self._feedback = feedback
    self._result: RuleResult = None
    self.model_components: typing.List[LayerModelComponent] = list()

rule_type property

rule_type

Returns the raster type rule validator.

Returns:

Type Description
RuleType

Raster type rule validator.

is_comparative

is_comparative()

Validator can be used for even one dataset.

Source code in src/cplus_plugin/lib/validation/validators.py
def is_comparative(self) -> bool:
    """Validator can be used for even one dataset."""
    return False

ResolutionValidator

ResolutionValidator(configuration, feedback)

Bases: BaseRuleValidator

Checks if datasets have the same spatial resolution.

Source code in src/cplus_plugin/lib/validation/validators.py
def __init__(self, configuration: RuleConfiguration, feedback: ValidationFeedback):
    self._config = configuration
    self._feedback = feedback
    self._result: RuleResult = None
    self.model_components: typing.List[LayerModelComponent] = list()

rule_type property

rule_type

Returns the no data value rule validator.

Returns:

Type Description
RuleType

No data value rule validator.

create_resolution_definition classmethod

create_resolution_definition(layer)

Creates a resolution definition tuple from a layer.

Parameters:

Name Type Description Default
layer QgsRasterLayer

Input layer.

required

Returns:

Type Description
tuple

Tuple containing x and y resolutions as well as the units.

Source code in src/cplus_plugin/lib/validation/validators.py
@classmethod
def create_resolution_definition(cls, layer: QgsRasterLayer):
    """Creates a resolution definition tuple from a layer.

    :param layer: Input layer.
    :type layer: QgsRasterLayer

    :returns: Tuple containing x and y resolutions as well
    as the units.
    :rtype: tuple
    """
    crs = layer.crs()
    if crs is None:
        crs_unit_str = tr("unknown")
    else:
        crs_unit_str = QgsUnitTypes.toAbbreviatedString(crs.mapUnits())

    # Tuple containing x, y (truncated to given decimal places) and units
    resolution_definition = (
        round(layer.rasterUnitsPerPixelX(), cls.DECIMAL_PLACES),
        round(layer.rasterUnitsPerPixelY(), cls.DECIMAL_PLACES),
        crs_unit_str,
    )
    return resolution_definition

resolution_definition_to_str classmethod

resolution_definition_to_str(resolution_definition)

Formats the resolution definition to a friendly-display string.

Parameters:

Name Type Description Default
resolution_definition tuple

Tuple containing x and y resolutions as well as the units.

required

Returns:

Type Description
str

Friendly display string.

Source code in src/cplus_plugin/lib/validation/validators.py
@classmethod
def resolution_definition_to_str(cls, resolution_definition: tuple) -> str:
    """Formats the resolution definition to a friendly-display string.

    :param resolution_definition: Tuple containing x and y resolutions as
    well as the units.
    :type resolution_definition: tuple

    :returns: Friendly display string.
    :rtype: str
    """
    if len(resolution_definition) < 3:
        return ""

    unit_str = (
        tr("unknown units")
        if not resolution_definition[2]
        else resolution_definition[2]
    )

    return f"X: {resolution_definition[0]!s} {unit_str}, Y: {resolution_definition[1]!s} {unit_str}"

Last update: October 2, 2024
Back to top