Skip to content

model_builder

Module for ModelBuilder class

!!! classes ModelBuilder

ModelBuilder (IModelBuilder)

Factory for creating models

Source code in workflow/model_builder.py
class ModelBuilder(IModelBuilder):
    """Factory for creating models"""

    def __init__(self, da_layer: IDataAccessLayer, logger: ILogger) -> None:
        self._logger = logger
        self._da_layer = da_layer

    def build_model(self, model_data: IModelData) -> IModel:
        """Creates a model based on model data.
        Current mapping works only for one dataset.

        Returns:
            IModel: instance of a model based on model data
        """

        self._logger.log_info("Creating rule-based model")

        datasets = [self._da_layer.read_input_dataset(ds) for ds in model_data.datasets]
        rules = list(ModelBuilder._create_rules(model_data.rules))

        mapping = model_data.datasets[0].mapping

        model: IModel = RuleBasedModel(
            datasets, rules, mapping, model_data.name, model_data.partition
        )

        return model

    @staticmethod
    def _create_rules(rule_data: List[IRuleData]) -> Iterable[IRule]:
        for rule_data_object in rule_data:
            yield ModelBuilder._create_rule(rule_data_object)

    @staticmethod
    def _set_default_fields(rule_data: IRuleData, rule: RuleBase):
        rule.description = rule_data.description
        rule.output_variable_name = rule_data.output_variable

    @staticmethod
    def _create_rule(rule_data: IRuleData) -> IRule:

        # from python >3.10 we can use match/case, better solution
        # until then disable pylint.
        # pylint: disable=too-many-branches
        if isinstance(rule_data, IMultiplyRuleData):
            rule = MultiplyRule(
                rule_data.name,
                [rule_data.input_variable],
                rule_data.multipliers,
                rule_data.date_range,
            )
        elif isinstance(rule_data, IDepthAverageRuleData):
            rule = DepthAverageRule(
                rule_data.name,
                rule_data.input_variables,
            )
        elif isinstance(rule_data, IFilterExtremesRuleData):
            rule = FilterExtremesRule(
                rule_data.name,
                rule_data.input_variables,
                rule_data.extreme_type,
                rule_data.distance,
                rule_data.time_scale,
                rule_data.mask,
            )
        elif isinstance(rule_data, ILayerFilterRuleData):
            rule = LayerFilterRule(
                rule_data.name,
                [rule_data.input_variable],
                rule_data.layer_number,
            )
        elif isinstance(rule_data, IAxisFilterRuleData):
            rule = AxisFilterRule(
                rule_data.name,
                [rule_data.input_variable],
                rule_data.element_index,
                rule_data.axis_name,
            )
        elif isinstance(rule_data, IStepFunctionRuleData):
            rule = StepFunctionRule(
                rule_data.name,
                rule_data.input_variable,
                rule_data.limits,
                rule_data.responses,
            )
        elif isinstance(rule_data, ITimeAggregationRuleData):
            rule = TimeAggregationRule(
                rule_data.name, [rule_data.input_variable], rule_data.operation
            )
            rule.settings.percentile_value = rule_data.percentile_value
            rule.settings.time_scale = rule_data.time_scale
        elif isinstance(rule_data, IRollingStatisticsRuleData):
            rule = RollingStatisticsRule(
                rule_data.name, [rule_data.input_variable], rule_data.operation
            )
            rule.settings.percentile_value = rule_data.percentile_value
            rule.settings.time_scale = rule_data.time_scale
            rule.period = rule_data.period
        elif isinstance(rule_data, ICombineResultsRuleData):
            rule = CombineResultsRule(
                rule_data.name,
                rule_data.input_variable_names,
                MultiArrayOperationType[rule_data.operation_type],
                rule_data.ignore_nan
            )
        elif isinstance(rule_data, IResponseCurveRuleData):
            rule = ResponseCurveRule(
                rule_data.name,
                rule_data.input_variable,
                rule_data.input_values,
                rule_data.output_values,
            )
        elif isinstance(rule_data, IFormulaRuleData):
            rule = FormulaRule(
                rule_data.name,
                rule_data.input_variable_names,
                rule_data.formula,
            )
        elif isinstance(rule_data, IClassificationRuleData):
            rule = ClassificationRule(
                rule_data.name, rule_data.input_variable_names, rule_data.criteria_table
            )
        else:
            error_str = (
                f"The rule type of rule '{rule_data.name}' is currently "
                "not implemented"
            )
            raise NotImplementedError(error_str)

        if isinstance(rule, RuleBase):
            ModelBuilder._set_default_fields(rule_data, rule)
        return rule

build_model(self, model_data)

Creates a model based on model data. Current mapping works only for one dataset.

Returns:

Type Description
IModel

instance of a model based on model data

Source code in workflow/model_builder.py
def build_model(self, model_data: IModelData) -> IModel:
    """Creates a model based on model data.
    Current mapping works only for one dataset.

    Returns:
        IModel: instance of a model based on model data
    """

    self._logger.log_info("Creating rule-based model")

    datasets = [self._da_layer.read_input_dataset(ds) for ds in model_data.datasets]
    rules = list(ModelBuilder._create_rules(model_data.rules))

    mapping = model_data.datasets[0].mapping

    model: IModel = RuleBasedModel(
        datasets, rules, mapping, model_data.name, model_data.partition
    )

    return model