Index: DamClients/DamPythonInterface/trunk/src/tests/test_data/test_segment.xml =================================================================== diff -u --- DamClients/DamPythonInterface/trunk/src/tests/test_data/test_segment.xml (revision 0) +++ DamClients/DamPythonInterface/trunk/src/tests/test_data/test_segment.xml (revision 3491) @@ -0,0 +1,4 @@ + + + + Index: DamClients/DamPythonInterface/trunk/src/tests/test_output/test_full_output.xml =================================================================== diff -u -r3490 -r3491 --- DamClients/DamPythonInterface/trunk/src/tests/test_output/test_full_output.xml (.../test_full_output.xml) (revision 3490) +++ DamClients/DamPythonInterface/trunk/src/tests/test_output/test_full_output.xml (.../test_full_output.xml) (revision 3491) @@ -33,6 +33,12 @@ + + + + + + Index: DamClients/DamPythonInterface/trunk/src/dampythoninterface/segment.py =================================================================== diff -u --- DamClients/DamPythonInterface/trunk/src/dampythoninterface/segment.py (revision 0) +++ DamClients/DamPythonInterface/trunk/src/dampythoninterface/segment.py (revision 3491) @@ -0,0 +1,104 @@ +# Copyright (C) Stichting Deltares 2021. All rights reserved. +# +# This file is part of the Dam Python Interface. +# +# The Dam Python Interface is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# All names, logos, and references to "Deltares" are registered trademarks of +# Stichting Deltares and remain full property of Stichting Deltares at all times. +# All rights reserved. + +from typing import List, Optional +import lxml.etree as et +from enum import IntEnum + +from .base_class import BaseDataClass + + +class SoilProfileTypeClass(IntEnum): + """ """ + + ProfileType1D = 0 + ProfileType2D = 1 + ProfileTypeStiFile = 2 + + +class SegmentFailureMechanismTypeClass(IntEnum): + """ """ + + All = 0 + Stability = 1 + Piping = 2 + Liquefaction = 3 + + +class SoilGeometryProbabilityElement(BaseDataClass): + """ + Dataclass that contains the propability and the failure mechanism type of an occuring profile. + + :param SoilProfileName: name of the selected soil profile + :param SoilProfileType: geometry type of the selected soil profile + :param SegmentFailureMechanismType: type of failure mechanism selected for a profile + :param Probability: probability of selected geometry + + """ + + SoilProfileName: str + SoilProfileType: SoilProfileTypeClass + SegmentFailureMechanismType: Optional[ + SegmentFailureMechanismTypeClass + ] = SegmentFailureMechanismTypeClass.Stability + Probability: float + + def serialize(self) -> et.Element: + """Function that serializes the SoilGeometryProbabilityElement dataclass.""" + soil_geometry_probability_root = et.Element("SoilGeometryProbability") + dictionary_of_values = self.dict() + soil_geometry_probability_root.set( + "SoilProfileName", dictionary_of_values.get("SoilProfileName") + ) + soil_geometry_probability_root.set( + "SoilProfileType", + str(dictionary_of_values.get("SoilProfileType").value), + ) + soil_geometry_probability_root.set( + "SegmentFailureMechanismType", + str(dictionary_of_values.get("SegmentFailureMechanismType").value), + ) + soil_geometry_probability_root.set( + "Probability", str(dictionary_of_values.get("Probability")) + ) + return soil_geometry_probability_root + + +class Segment(BaseDataClass): + """ + Dataclass for a segment + + :param Name: name of the segment + :param SoilGeometryProbability: List of SoilGeometryProbabilityElement + + """ + + Name: str + SoilGeometryProbability: List[SoilGeometryProbabilityElement] = [] + + def serialize(self) -> et.Element: + """Function that serializes the Segment dataclass.""" + segment_root = et.Element("Segment") + dictionary_of_values = self.dict() + segment_root.set("Name", dictionary_of_values.get("Name")) + for soilgeometry in self.SoilGeometryProbability: + segment_root.append(soilgeometry.serialize()) + return segment_root Index: DamClients/DamPythonInterface/trunk/doc/source/dev/input.rst =================================================================== diff -u -r3490 -r3491 --- DamClients/DamPythonInterface/trunk/doc/source/dev/input.rst (.../input.rst) (revision 3490) +++ DamClients/DamPythonInterface/trunk/doc/source/dev/input.rst (.../input.rst) (revision 3491) @@ -43,4 +43,13 @@ .. automodule:: dampythoninterface.soilprofile1D :members: + :undoc-members: + + +Segment +------- + + +.. automodule:: dampythoninterface.segment + :members: :undoc-members: \ No newline at end of file Index: DamClients/DamPythonInterface/trunk/src/dampythoninterface/input.py =================================================================== diff -u -r3490 -r3491 --- DamClients/DamPythonInterface/trunk/src/dampythoninterface/input.py (.../input.py) (revision 3490) +++ DamClients/DamPythonInterface/trunk/src/dampythoninterface/input.py (.../input.py) (revision 3491) @@ -30,6 +30,7 @@ from .base_class import BaseDataClass from .stability_parameters import StabilityParameters from .soilprofile1D import SoilProfile1D +from .segment import Segment class DamInput(BaseDataClass): @@ -44,10 +45,11 @@ Soils: List[Soil] = [] StabilityParameters: StabilityParameters SoilProfiles1D: List[SoilProfile1D] = [] + Segments: List[Segment] = [] @validator("SoilProfiles1D") def soil_profiles_contain_soils(cls, v, values, **kwargs): - soils_names = [soil.Name for soil in values["Soils"]] + soils_names = [soil.Name for soil in values.get("Soils")] soilprofiles = v for soilprofile in soilprofiles: for layer in soilprofile.Layers1D: @@ -59,6 +61,20 @@ ) return v + @validator("Segments") + def segment_contains_existing_profile(cls, v, values, **kwargs): + profile_names = [profile.Name for profile in values.get("SoilProfiles1D")] + segments = v + for segment in segments: + for soilgeometry in segment.SoilGeometryProbability: + if not (soilgeometry.SoilProfileName in profile_names): + raise ValueError( + f"Profile {soilgeometry.SoilProfileName} \ + is part of segment {segment.Name} but not\ + part of the profile element." + ) + return v + def ExportToXml(self, xml_file: Path) -> None: """ Function that export the DamInput dataclass to an xml that can be used as input of the DAMengine. @@ -82,6 +98,11 @@ for soil_profile in self.SoilProfiles1D: soilprofiles_root.append(soil_profile.serialize()) input_root.append(soilprofiles_root) + # add segments + segments_root = et.Element("Elements") + for segment in self.Segments: + segments_root.append(segment.serialize()) + input_root.append(segments_root) # add stability parameters to input root input_root.append(self.StabilityParameters.serialize()) # append soil aquifers Index: DamClients/DamPythonInterface/trunk/src/tests/test_segment.py =================================================================== diff -u --- DamClients/DamPythonInterface/trunk/src/tests/test_segment.py (revision 0) +++ DamClients/DamPythonInterface/trunk/src/tests/test_segment.py (revision 3491) @@ -0,0 +1,80 @@ +# Copyright (C) Stichting Deltares 2021. All rights reserved. +# +# This file is part of the Dam Python Interface. +# +# The Dam Python Interface is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# All names, logos, and references to "Deltares" are registered trademarks of +# Stichting Deltares and remain full property of Stichting Deltares at all times. +# All rights reserved. + +from dampythoninterface.segment import ( + Segment, + SoilGeometryProbabilityElement, + SoilProfileTypeClass, + SegmentFailureMechanismTypeClass, +) + +from .utils import TestUtils + +import pytest +from pathlib import Path +from lxml import etree + + +class TestSegment: + def define_segment(self) -> Segment: + # first define the soil layers + profile_1 = SoilGeometryProbabilityElement( + SoilProfileName="soilprofile_01", + SoilProfileType=SoilProfileTypeClass.ProfileType1D, + Probability=1, + SegmentFailureMechanismType=SegmentFailureMechanismTypeClass.Stability, + ) + profile_2 = SoilGeometryProbabilityElement( + SoilProfileName="soilprofile_01", + SoilProfileType=SoilProfileTypeClass.ProfileType1D, + Probability=1, + SegmentFailureMechanismType=SegmentFailureMechanismTypeClass.Piping, + ) + return Segment( + Name="Test segment", SoilGeometryProbability=[profile_1, profile_2] + ) + + @pytest.mark.unittest + def test_if_segment_can_be_initialized(self): + segment = self.define_segment() + # test expectations + assert segment.Name == "Test segment" + assert len(segment.SoilGeometryProbability) == 2 + assert segment.SoilGeometryProbability[-1].SoilProfileName == "soilprofile_01" + + @pytest.mark.unittest + def test_serialize(self): + # initialize the stabilty parameters class + segment = self.define_segment() + # run test + root = segment.serialize() + # test output + xml_output = Path(TestUtils.get_output_test_data_dir(""), "test_segment.xml") + tree = etree.ElementTree(root) + tree.write(str(xml_output), pretty_print=True) + # get template file + xml_test_data = Path( + TestUtils.get_test_data_dir("", "test_data"), + "test_segment.xml", + ) + # Line by line comparison + for output_file, test_file in zip(open(xml_output), open(xml_test_data)): + assert output_file.strip() == test_file.strip() Index: DamClients/DamPythonInterface/trunk/src/tests/test_input.py =================================================================== diff -u -r3490 -r3491 --- DamClients/DamPythonInterface/trunk/src/tests/test_input.py (.../test_input.py) (revision 3490) +++ DamClients/DamPythonInterface/trunk/src/tests/test_input.py (.../test_input.py) (revision 3491) @@ -34,6 +34,12 @@ BishopTangentLinesDefinitionType, GridDeterminationType, ) +from dampythoninterface.segment import ( + Segment, + SoilProfileTypeClass, + SoilGeometryProbabilityElement, + SegmentFailureMechanismTypeClass, +) from dampythoninterface.soilprofile1D import ( SoilProfile1D, Layer1D, @@ -43,6 +49,24 @@ class TestDamInput: + def define_segment(self, soil_profile_names: List[str]) -> List[Segment]: + # first define the soil layers + profile_1 = SoilGeometryProbabilityElement( + SoilProfileName=soil_profile_names[0], + SoilProfileType=SoilProfileTypeClass.ProfileType1D, + Probability=1, + SegmentFailureMechanismType=SegmentFailureMechanismTypeClass.Stability, + ) + profile_2 = SoilGeometryProbabilityElement( + SoilProfileName=soil_profile_names[1], + SoilProfileType=SoilProfileTypeClass.ProfileType1D, + Probability=1, + SegmentFailureMechanismType=SegmentFailureMechanismTypeClass.Piping, + ) + return [ + Segment(Name="Test segment", SoilGeometryProbability=[profile_1, profile_2]) + ] + def create_surface_lines(self) -> List[SurfaceLine]: # Create surface lines points_available = [ @@ -121,19 +145,44 @@ soils = self.create_soils() test_stabilty_parameters = self.create_stability_parameters() soil_profiles = self.create_profiles([soils[0].Name, "wrong soil name"]) + segments = self.define_segment([soil_profiles[0].Name, soil_profiles[0].Name]) # run test error_message = "Soil with name wrong soil name" with pytest.raises(ValueError) as e_info: DamInput( SurfaceLines=list_of_surface_lines, Soils=soils, StabilityParameters=test_stabilty_parameters, + Segments=segments, SoilProfiles1D=soil_profiles, ) generated_error_message = str(e_info.value) assert error_message in generated_error_message @pytest.mark.integrationtest + def test_soil_profiles_contain_segments(self): + # Create surface lines + list_of_surface_lines = self.create_surface_lines() + # create soil class + soils = self.create_soils() + # Create stability parameters + test_stabilty_parameters = self.create_stability_parameters() + soil_profiles = self.create_profiles([soils[0].Name, soils[1].Name]) + segments = self.define_segment([soil_profiles[0].Name, "Wrong profile"]) + # run test + error_message = "Wrong profile" + with pytest.raises(ValueError) as e_info: + DamInput( + SurfaceLines=list_of_surface_lines, + Soils=soils, + StabilityParameters=test_stabilty_parameters, + SoilProfiles1D=soil_profiles, + Segments=segments, + ) + generated_error_message = str(e_info.value) + assert error_message in generated_error_message + + @pytest.mark.integrationtest def test_ExportToXml(self): # Create surface lines list_of_surface_lines = self.create_surface_lines() @@ -142,12 +191,14 @@ # Create stability parameters test_stabilty_parameters = self.create_stability_parameters() soil_profiles = self.create_profiles([soils[0].Name, soils[1].Name]) + segments = self.define_segment([soil_profiles[0].Name, soil_profiles[0].Name]) # Make input class model = DamInput( SurfaceLines=list_of_surface_lines, Soils=soils, StabilityParameters=test_stabilty_parameters, SoilProfiles1D=soil_profiles, + Segments=segments, ) assert model # run test