Skip to content

Commit

Permalink
Merge pull request #95 from Deltares/fix/83-removal-of-outside-grass-…
Browse files Browse the repository at this point in the history
…and-clay-layers-with-outside-reinforcement

Fix/83 removal of outside grass and clay layers with outside reinforcement
  • Loading branch information
Carsopre authored Oct 23, 2023
2 parents 407e371 + 0d3eddf commit c547550
Show file tree
Hide file tree
Showing 40 changed files with 281 additions and 240 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Reinforcement Layers Wrapper

::: koswat.calculations.reinforcement_layers.reinforcement_layer_protocol
::: koswat.calculations.reinforcement_layers.reinforcement_base_layer
::: koswat.calculations.reinforcement_layers.reinforcement_coating_layer
::: koswat.calculations.reinforcement_layers.reinforcement_layers_wrapper

# Reinforcement Layers Wrapper builders

::: koswat.calculations.reinforcement_layers.outside_slope_reinforcement_layers_wrapper_builder
::: koswat.calculations.reinforcement_layers.standard_reinforcement_layers_wrapper_builder

This file was deleted.

15 changes: 11 additions & 4 deletions koswat/calculations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@ This module contains the information on calculating a reinforcement (`Reinforcem

The module is divided as:
- __io__: Input / output module containing the concrete importers and exporters for the models here defined.
- __outside_slope_reinforcement__: Module containing the definition of all `OutsideSlopeReinforcementProfile` implementations.
- __standard_reinforcement__: Module containing the definition of all `StandardReinforcementProfile` implementations.
- __reinforcement_layers__: Module containing the definition of all `ReinforcementLayerProtocol` implementations and their builders.
- __outside_slope_reinforcement__: Module containing the definition of all `OutsideSlopeReinforcementProfile` implementations and their builders.
- __standard_reinforcement__: Module containing the definition of all `StandardReinforcementProfile` implementations and their builders.
- __protocols__: Module where the `typing.Protocol` concrete definitions used across the whole calculation modules are saved.

At the same time we expose directly the
- `ReinforcementLayersWrapper`: Concrete implementation of `KoswatLayersWrapperProtocol` which uses `ReinforcementBaseLayer` and `ReinforcementCoatingLayer` instead (both from instances of `ReinforcementLayerProtocol`).
- `ReinforcementProfileBuilderFactory`: Factory to retrieve the correct instances of a `ReinforcementProfileBuilderProtocol`.

## Design decisions.
It could be argued that some of the code could be reduced by using abstractions or simple inheritance. However I opted for 'duplicating' methods logic in order to reduce the dependency between classes thus making them totally independent. Alas the usage of protocols over abstractions.

A reinforcement calculation will naturally be found in its respective `*_profile_calculation.py` file. This way we isolate the logic to get each one of the values that compose a specific reinforcement profile, allowing us for better maintainability and verification.
A reinforcement calculation will naturally be found in its respective `*_profile_calculation.py` file. This way we isolate the logic to get each one of the values that compose a specific reinforcement profile, allowing us for better maintainability and verification.

## Future work.
After a few iterations of adding / modifying how a reinforcement is calculated, it is preferred to refactor the process by splitting the process into two steps:
1. Calculate the new reinforced profile.
2. Calculate the added / removed / reused materials based on the geometries / layers of point 1.

This work implies the introduction and modification of existing `ReinforcementProfileProtocol` classes, as well as how the builders in the `reinforcement_layers` module function, because they will no longer require to calculate "on the fly" geometries related to added / removed / reused material.
4 changes: 3 additions & 1 deletion koswat/calculations/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from koswat.calculations.reinforcement_layers_wrapper import ReinforcementLayersWrapper
from koswat.calculations.reinforcement_layers.reinforcement_layers_wrapper import (
ReinforcementLayersWrapper,
)
from koswat.calculations.reinforcement_profile_builder_factory import (
ReinforcementProfileBuilderFactory,
)
7 changes: 4 additions & 3 deletions koswat/calculations/io/reinforced_profile_plot_exporter.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from pathlib import Path
from typing import List

from koswat.calculations.protocols import ReinforcementProfileProtocol
from koswat.calculations.reinforcement_layers_wrapper import ReinforcementCoatingLayer
from koswat.calculations.reinforcement_layers.reinforcement_layers_wrapper import (
ReinforcementCoatingLayer,
)
from koswat.dike.layers.koswat_layer_protocol import KoswatLayerProtocol
from koswat.plots.dike.koswat_layers_wrapper_plot import KoswatLayersWrapperPlot
from koswat.plots.geometries.highlight_geometry_plot import HighlightGeometryPlot
Expand Down Expand Up @@ -44,7 +45,7 @@ def _export_layers(
self,
output_file: Path,
layer_to_highlight,
layers_to_plot: List[KoswatLayerProtocol],
layers_to_plot: list[KoswatLayerProtocol],
):
# Define canvas
with KoswatFigureContextHandler(
Expand Down
3 changes: 0 additions & 3 deletions koswat/calculations/outside_slope_reinforcement/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
CofferdamReinforcementProfile,
CofferdamReinforcementProfileCalculation,
)
from koswat.calculations.outside_slope_reinforcement.outside_slope_reinforcement_layers_wrapper_builder import (
OutsideSlopeReinforcementLayersWrapperBuilder,
)
from koswat.calculations.outside_slope_reinforcement.outside_slope_reinforcement_profile import (
OutsideSlopeReinforcementProfile,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from typing import Type

from koswat.calculations.outside_slope_reinforcement.cofferdam import (
CofferdamReinforcementProfile,
CofferdamReinforcementProfileCalculation,
)
from koswat.calculations.outside_slope_reinforcement.outside_slope_reinforcement_layers_wrapper_builder import (
from koswat.calculations.reinforcement_layers.outside_slope_reinforcement_layers_wrapper_builder import (
OutsideSlopeReinforcementLayersWrapperBuilder,
)
from koswat.calculations.outside_slope_reinforcement.outside_slope_reinforcement_profile import (
Expand All @@ -15,7 +13,9 @@
ReinforcementInputProfileProtocol,
ReinforcementProfileBuilderProtocol,
)
from koswat.calculations.reinforcement_layers_wrapper import ReinforcementLayersWrapper
from koswat.calculations.reinforcement_layers.reinforcement_layers_wrapper import (
ReinforcementLayersWrapper,
)
from koswat.configuration.settings import KoswatScenario
from koswat.dike.characteristic_points.characteristic_points import CharacteristicPoints
from koswat.dike.characteristic_points.characteristic_points_builder import (
Expand All @@ -27,16 +27,15 @@
class OutsideSlopeReinforcementProfileBuilder(ReinforcementProfileBuilderProtocol):
base_profile: KoswatProfileBase
scenario: KoswatScenario
reinforcement_profile_type: Type[OutsideSlopeReinforcementProfile]
reinforcement_profile_type: type[OutsideSlopeReinforcementProfile]

@staticmethod
def get_standard_reinforcement_calculator(
reinforcement_type: Type[OutsideSlopeReinforcementProfile],
reinforcement_type: type[OutsideSlopeReinforcementProfile],
):
if issubclass(reinforcement_type, CofferdamReinforcementProfile):
return CofferdamReinforcementProfileCalculation
else:
raise NotImplementedError(f"Type {reinforcement_type} not supported.")
raise NotImplementedError(f"Type {reinforcement_type} not supported.")

def _get_reinforcement_profile_input(
self,
Expand Down
4 changes: 3 additions & 1 deletion koswat/calculations/protocols/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Calculations protocols
The following protocols can be found here:
The following protocols __regarding creation of input profiles__ can be found here:

- `ReinforcementInputProfileProtocol`: An extension of `KoswatInputProfileProtocol`.
- `ReinforcementProfileCalculationProtocol`: Extension of the `BuilderProtocol` to define the required calculations that will return the input data required to create a `ReinforcementInputProfileProtocol`.
- `ReinforcementLayerProtocol`: An extension of the `KoswatLayerProtocol` which contains information regarding the new layer geometry, surface as well as the preivous layer geometry.

- `ReinforcementProfileProtocol`: An extension of `KoswatProfileProtocol` which uses `ReinforcementLayersWrapper` instead.
- `ReinforcementProfileBuilderProtocol`: Extension of the `BuilderProtocol` to specify the required data needed to generate a `ReinforcementProfileProtocol`.

How to define "layers" is specified in the `koswat.calculations.reinforcement_layers` module.
3 changes: 3 additions & 0 deletions koswat/calculations/protocols/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@
from koswat.calculations.protocols.reinforcement_profile_protocol import (
ReinforcementProfileProtocol,
)

# NOTE! ReinforcementLayerProtocol is not included here due to a circular dependency
# created with all the protocols declared on this module and ReinforcementLayersWrapper.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Protocol, Type, runtime_checkable
from typing import Protocol, runtime_checkable

from koswat.calculations.protocols.reinforcement_profile_protocol import (
ReinforcementProfileProtocol,
Expand All @@ -12,7 +12,7 @@
class ReinforcementProfileBuilderProtocol(BuilderProtocol, Protocol):
base_profile: KoswatProfileBase
scenario: KoswatScenario
reinforcement_profile_type: Type[ReinforcementProfileProtocol]
reinforcement_profile_type: type[ReinforcementProfileProtocol]

def build(self) -> ReinforcementProfileProtocol:
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from koswat.calculations.protocols.reinforcement_input_profile_protocol import (
ReinforcementInputProfileProtocol,
)
from koswat.calculations.reinforcement_layers_wrapper import ReinforcementLayersWrapper
from koswat.calculations.reinforcement_layers.reinforcement_layers_wrapper import ReinforcementLayersWrapper
from koswat.dike.koswat_profile_protocol import KoswatProfileProtocol


Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
from shapely.geometry import Point, Polygon

from koswat.calculations.reinforcement_layers_wrapper import (
from koswat.calculations.reinforcement_layers.reinforcement_layer_protocol import (
ReinforcementLayerProtocol,
)
from koswat.calculations.reinforcement_layers.reinforcement_base_layer import (
ReinforcementBaseLayer,
)
from koswat.calculations.reinforcement_layers.reinforcement_coating_layer import (
ReinforcementCoatingLayer,
ReinforcementLayerProtocol,
)
from koswat.calculations.reinforcement_layers.reinforcement_layers_wrapper import (
ReinforcementLayersWrapper,
)
from koswat.core.geometries.calc_library import get_polygon_surface_points
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from __future__ import annotations


from shapely.geometry import LineString, Polygon, MultiPolygon
from koswat.calculations.reinforcement_layers.reinforcement_layer_protocol import (
ReinforcementLayerProtocol,
)
from koswat.core.geometries.calc_library import get_polygon_coordinates
from koswat.dike.layers.base_layer import KoswatBaseLayer

from koswat.dike.material.koswat_material_type import KoswatMaterialType


class ReinforcementBaseLayer(ReinforcementLayerProtocol):
material_type: KoswatMaterialType
outer_geometry: Polygon
material_geometry: Polygon
upper_points: LineString
new_layer_geometry: Polygon | MultiPolygon
new_layer_surface: LineString
old_layer_geometry: Polygon

def __init__(self) -> None:
self.material_type = None
self.outer_geometry = None
self.material_geometry = None
self.upper_points = None
self.new_layer_geometry = None

def as_data_dict(self) -> dict:
_geometry = []
if self.outer_geometry:
_geometry = list(get_polygon_coordinates(self.outer_geometry).coords)
return dict(
material=self.material_type.name,
geometry=_geometry,
)

@classmethod
def from_koswat_base_layer(
cls, base_layer: KoswatBaseLayer
) -> ReinforcementBaseLayer:
_reinforced_base_layer = cls()
_reinforced_base_layer.__dict__ = base_layer.__dict__
return _reinforced_base_layer
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from __future__ import annotations


from shapely.geometry import LineString, Polygon, MultiPolygon
from koswat.calculations.reinforcement_layers.reinforcement_layer_protocol import (
ReinforcementLayerProtocol,
)

from koswat.core.geometries.calc_library import get_polygon_coordinates
from koswat.dike.layers.coating_layer import KoswatCoatingLayer
from koswat.dike.material.koswat_material_type import KoswatMaterialType


class ReinforcementCoatingLayer(ReinforcementLayerProtocol):
material_type: KoswatMaterialType
outer_geometry: Polygon
material_geometry: Polygon
upper_points: LineString
old_layer_geometry: Polygon
new_layer_geometry: Polygon | MultiPolygon
new_layer_surface: LineString
removal_layer_geometry: Polygon

def __init__(self) -> None:
self.material_type = None
self.outer_geometry = None
self.material_geometry = None
self.upper_points = None
self.new_layer_geometry = None
self.removal_layer_geometry = None

def as_data_dict(self) -> dict:
_geometry = []
if self.outer_geometry:
_geometry = list(get_polygon_coordinates(self.outer_geometry).coords)
return dict(
material=self.material_type.name,
depth=self.depth,
geometry=_geometry,
)

@classmethod
def from_koswat_coating_layer(
cls, coating_layer: KoswatCoatingLayer
) -> ReinforcementCoatingLayer:
_reinforced_coating_layer = cls()
_reinforced_coating_layer.__dict__ = coating_layer.__dict__
return _reinforced_coating_layer

@classmethod
def with_same_outer_geometry(
cls, coating_layer: KoswatCoatingLayer
) -> ReinforcementCoatingLayer:
"""
Creates a new reinforcement coating layer which does not differ
in geometry from the provided coating layer. This was found to
be needed in KOSWAT_82.
Args:
coating_layer (KoswatCoatingLayer): Base coating layer.
Returns:
ReinforcementCoatingLayer: Resulting coating layer with "empty"
polygons for added / removed (layer) geometries.
"""
_reinforced_coating_layer = cls.from_koswat_coating_layer(coating_layer)
_reinforced_coating_layer.old_layer_geometry = coating_layer.outer_geometry
_reinforced_coating_layer.removal_layer_geometry = Polygon()
_reinforced_coating_layer.new_layer_geometry = Polygon()
_reinforced_coating_layer.new_layer_surface = LineString()
return _reinforced_coating_layer
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from typing import Protocol, runtime_checkable
from koswat.dike.layers import KoswatLayerProtocol
from shapely.geometry import LineString, Polygon, MultiPolygon


@runtime_checkable
class ReinforcementLayerProtocol(KoswatLayerProtocol, Protocol):
new_layer_geometry: Polygon | MultiPolygon
new_layer_surface: LineString
old_layer_geometry: Polygon
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from koswat.calculations.reinforcement_layers.reinforcement_layer_protocol import (
ReinforcementLayerProtocol,
)
from koswat.calculations.reinforcement_layers.reinforcement_base_layer import (
ReinforcementBaseLayer,
)
from koswat.calculations.reinforcement_layers.reinforcement_coating_layer import (
ReinforcementCoatingLayer,
)
from koswat.dike.layers.layers_wrapper import KoswatLayersWrapperProtocol
from koswat.dike.material.koswat_material_type import KoswatMaterialType


class ReinforcementLayersWrapper(KoswatLayersWrapperProtocol):
base_layer: ReinforcementBaseLayer
coating_layers: list[ReinforcementCoatingLayer]

def __init__(self) -> None:
self.base_layer = None
self.coating_layers = []

def as_data_dict(self) -> dict:
return dict(
base_layer=self.base_layer.as_data_dict(),
coating_layers=[c_l.as_data_dict() for c_l in self.coating_layers],
)

def get_layer(self, material_type: KoswatMaterialType) -> ReinforcementCoatingLayer:
_found_layer = next(
(
_layer
for _layer in self.coating_layers
if _layer.material_type == material_type
),
None,
)
if not _found_layer:
raise ValueError(
"Material {} not present in the layers.".format(material_type.name)
)
return _found_layer

@property
def layers(self) -> list[ReinforcementLayerProtocol]:
"""
All the stored layers being the `KoswatBaseLayer` the latest one in the collection.
Returns:
List[KoswatLayerProtocol]: Ordered list of `KoswatLayerProtocol`.
"""
_layers = []
_layers.extend(self.coating_layers)
if self.base_layer:
_layers.append(self.base_layer)
return _layers
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from shapely.geometry import Point, Polygon

from koswat.calculations.reinforcement_layers_wrapper import (
from koswat.calculations.reinforcement_layers.reinforcement_layers_wrapper import (
ReinforcementBaseLayer,
ReinforcementCoatingLayer,
ReinforcementLayersWrapper,
Expand Down
Loading

0 comments on commit c547550

Please sign in to comment.