Skip to content

Structures

Structures: .ini files

Models

TODO Implement the following structures - Bridge - Generalstructure - Long culvert - Gate

Add comments for these structures. Maybe link them to descriptions of Fields?

CulvertSubType (str, Enum)

An enumeration.

Dambreak (Structure) pydantic-model

check_location(values: dict) -> dict classmethod

Verifies whether the location for this structure contains valid values for numCoordinates, xCoordinates and yCoordinates or instead is using a polyline file.

Parameters:

Name Type Description Default
values dict

Dictionary of validated values to create a Dambreak.

required

Exceptions:

Type Description
ValueError

When the values dictionary does not contain valid coordinates or polyline file..

Returns:

Type Description
dict

Dictionary of validated values.

Source code in hydrolib/core/io/structure/models.py
@root_validator
@classmethod
def check_location(cls, values: dict) -> dict:
    """
    Verifies whether the location for this structure contains valid values for
    numCoordinates, xCoordinates and yCoordinates or instead is using a polyline file.

    Args:
        values (dict): Dictionary of validated values to create a Dambreak.

    Raises:
        ValueError: When the values dictionary does not contain valid coordinates or polyline file..

    Returns:
        dict: Dictionary of validated values.
    """
    if (
        Structure.validate_coordinates_in_model(values)
        or values.get("polylinefile", None) is not None
    ):
        return values

    raise ValueError(
        "`num/x/yCoordinates` or `polylineFile` are mandatory for a Dambreak structure."
    )

validate_algorithm(value: str) -> DambreakAlgorithm classmethod

Validates the algorithm parameter for the dambreak structure.

Parameters:

Name Type Description Default
value int

algorithm value read from the user's input.

required

Exceptions:

Type Description
ValueError

When the value given is not of type int.

ValueError

When the value given is not in the range [1,3]

Returns:

Type Description
int

Validated value.

Source code in hydrolib/core/io/structure/models.py
@validator("algorithm", pre=True)
@classmethod
def validate_algorithm(cls, value: str) -> DambreakAlgorithm:
    """
    Validates the algorithm parameter for the dambreak structure.

    Args:
        value (int): algorithm value read from the user's input.

    Raises:
        ValueError: When the value given is not of type int.
        ValueError: When the value given is not in the range [1,3]

    Returns:
        int: Validated value.
    """
    int_value = -1
    try:
        int_value = int(value)
    except Exception:
        raise ValueError("Dambreak algorithm value should be of type int.")
    if 0 < int_value <= 3:
        return DambreakAlgorithm(int_value)
    raise ValueError("Dambreak algorithm value should be 1, 2 or 3.")

validate_dambreak_levels_and_widths(field_value: Optional[pathlib.Path], values: dict) -> Optional[pathlib.Path] classmethod

Validates whether a dambreak can be created with the given dambreakLevelsAndWidths property. This property should be given when the algorithm value is 3.

Parameters:

Name Type Description Default
field_value Optional[Path]

Value given for dambreakLevelsAndWidths.

required
values dict

Dictionary of values already validated (assuming algorithm is in it).

required

Exceptions:

Type Description
ValueError

When algorithm value is not 3 and field_value has a value.

Returns:

Type Description
Optional[Path]

The value given for dambreakLevelsAndwidths.

Source code in hydrolib/core/io/structure/models.py
@validator("dambreaklevelsandwidths")
@classmethod
def validate_dambreak_levels_and_widths(
    cls, field_value: Optional[Path], values: dict
) -> Optional[Path]:
    """
    Validates whether a dambreak can be created with the given dambreakLevelsAndWidths
    property. This property should be given when the algorithm value is 3.

    Args:
        field_value (Optional[Path]): Value given for dambreakLevelsAndWidths.
        values (dict): Dictionary of values already validated (assuming algorithm is in it).

    Raises:
        ValueError: When algorithm value is not 3 and field_value has a value.

    Returns:
        Optional[Path]: The value given for dambreakLevelsAndwidths.
    """
    # Retrieve the algorithm value (if not found use 0).
    algorithm_value = values.get("algorithm", 0)
    if field_value is not None and algorithm_value != 3:
        # dambreakLevelsAndWidths can only be set when algorithm = 3
        raise ValueError(
            f"Dambreak field dambreakLevelsAndWidths can only be set when algorithm = 3, current value: {algorithm_value}."
        )
    return field_value

DambreakAlgorithm (int, Enum)

An enumeration.

FlowDirection (str, Enum)

An enumeration.

Structure (INIBasedModel) pydantic-model

check_location(values: dict) -> dict classmethod

Validates the location of the structure based on the given parameters. For instance, if a branchid is given, then it is expected also the chainage, otherwise numcoordinates xcoordinates and ycoordinates shall be expected.

Parameters:

Name Type Description Default
values dict

Dictionary of values validated for the new structure.

required

Exceptions:

Type Description
ValueError

When branchid or chainage values are not valid (empty strings).

ValueError

When the number of xcoordinates and ycoordinates do not match numcoordinates.

Returns:

Type Description
dict

Dictionary of values validated for the new structure.

Source code in hydrolib/core/io/structure/models.py
@root_validator
@classmethod
def check_location(cls, values: dict) -> dict:
    """
    Validates the location of the structure based on the given parameters.
    For instance, if a branchid is given, then it is expected also the chainage,
    otherwise numcoordinates xcoordinates and ycoordinates shall be expected.

    Args:
        values (dict): Dictionary of values validated for the new structure.

    Raises:
        ValueError: When branchid or chainage values are not valid (empty strings).
        ValueError: When the number of xcoordinates and ycoordinates do not match numcoordinates.

    Returns:
        dict: Dictionary of values validated for the new structure.
    """
    filtered_values = {k: v for k, v in values.items() if v is not None}
    type = filtered_values.get("type", "").lower()
    if type == "compound" or issubclass(cls, Compound):
        # Compound structure does not require a location specification.
        return values

    # Apparently the overriding functionality does not seem to work in pydantic,
    # therefore we need to do this.
    if issubclass(cls, Dambreak):
        # The check on only_coordinates_structures remains as that handles the case
        # where a 'flat structure' is created giving the type string name "dambreak".
        return values

    coordinates_in_model = Structure.validate_coordinates_in_model(filtered_values)

    # Exception -> LongCulvert requires coordinates_in_model, but not branchId and chainage.
    only_coordinates_structures = dict(
        longculvert="LongCulvert", dambreak="Dambreak"
    )
    if type in only_coordinates_structures.keys():
        assert (
            coordinates_in_model
        ), f"`num/x/yCoordinates` are mandatory for a {only_coordinates_structures[type]} structure."
        return values

    branch_and_chainage_in_model = Structure.validate_branch_and_chainage_in_model(
        filtered_values
    )
    assert (
        branch_and_chainage_in_model or coordinates_in_model
    ), "Specify location either by setting `branchId` and `chainage` or `num/x/yCoordinates` fields."
    return values

validate(v) classmethod

Try to iniatialize subclass based on the type field. This field is compared to each type field of the derived models of Structure. The derived model with an equal structure type will be initialized.

Exceptions:

Type Description
ValueError

When the given type is not a known structure type.

Source code in hydrolib/core/io/structure/models.py
@classmethod
def validate(cls, v):
    """Try to iniatialize subclass based on the `type` field.
    This field is compared to each `type` field of the derived models of `Structure`.
    The derived model with an equal structure type will be initialized.

    Raises:
        ValueError: When the given type is not a known structure type.
    """

    # should be replaced by discriminated unions once merged
    # https://github.com/samuelcolvin/pydantic/pull/2336
    if isinstance(v, dict):
        for c in cls.__subclasses__():
            if (
                c.__fields__.get("type").default.lower()
                == v.get("type", "").lower()
            ):
                v = c(**v)
                break
        else:
            raise ValueError(
                f"Type of {cls.__name__} with id={v.get('id', '')} and type={v.get('type', '')} is not recognized."
            )
    return super().validate(v)

validate_branch_and_chainage_in_model(values: dict) -> bool staticmethod

Static method to validate whether the given branchid and chainage values match the expectation of a new structure.

Parameters:

Name Type Description Default
values dict

Dictionary of values to be used to generate a structure.

required

Exceptions:

Type Description
ValueError

When the value for branchid or chainage are not valid.

Returns:

Type Description
bool

Result of valid branchid / chainage in dictionary.

Source code in hydrolib/core/io/structure/models.py
@staticmethod
def validate_branch_and_chainage_in_model(values: dict) -> bool:
    """
    Static method to validate whether the given branchid and chainage values
    match the expectation of a new structure.

    Args:
        values (dict): Dictionary of values to be used to generate a structure.

    Raises:
        ValueError: When the value for branchid or chainage are not valid.

    Returns:
        bool: Result of valid branchid / chainage in dictionary.
    """
    branchid = values.get("branchid", None)
    if branchid is None:
        return False

    chainage = values.get("chainage", None)
    if str_is_empty_or_none(branchid) or chainage is None:
        raise ValueError(
            "A valid value for branchId and chainage is required when branchId key is specified."
        )
    return True

validate_coordinates_in_model(values: dict) -> bool staticmethod

Static method to validate whether the given values match the expectations of a structure to define its coordinates.

Parameters:

Name Type Description Default
values dict

Dictionary of values to be used to generate a structure.

required

Exceptions:

Type Description
ValueError

When the given coordinates is less than 2.

ValueError

When the given coordinates do not match in expected size.

Returns:

Type Description
bool

Result of valid coordinates in dictionary.

Source code in hydrolib/core/io/structure/models.py
@staticmethod
def validate_coordinates_in_model(values: dict) -> bool:
    """
    Static method to validate whether the given values match the expectations
    of a structure to define its coordinates.

    Args:
        values (dict): Dictionary of values to be used to generate a structure.

    Raises:
        ValueError: When the given coordinates is less than 2.
        ValueError: When the given coordinates do not match in expected size.

    Returns:
        bool: Result of valid coordinates in dictionary.
    """
    searched_keys = ["numcoordinates", "xcoordinates", "ycoordinates"]
    if any(values.get(k, None) is None for k in searched_keys):
        return False

    n_coords = values["numcoordinates"]
    if n_coords < 2:
        raise ValueError(
            f"Expected at least 2 coordinates, but only {n_coords} declared."
        )

    def get_coord_len(coord: str) -> int:
        if values[coord] is None:
            return 0
        return len(values[coord])

    len_x_coords = get_coord_len("xcoordinates")
    len_y_coords = get_coord_len("ycoordinates")
    if n_coords == len_x_coords == len_y_coords:
        return True
    raise ValueError(
        f"Expected {n_coords} coordinates, given {len_x_coords} for xCoordinates and {len_y_coords} for yCoordinates."
    )
Back to top