Skip to content

Commit

Permalink
changes to types. separate utility functions
Browse files Browse the repository at this point in the history
  • Loading branch information
HansKallekleiv committed Sep 20, 2023
1 parent cf79ef1 commit cb750ae
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 77 deletions.
64 changes: 36 additions & 28 deletions backend/src/backend/primary/routers/surface/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,49 +51,57 @@ def to_api_surface_directory(
"""
Convert Sumo surface directory to API surface directory
"""
surface_metas: List[schemas.SurfaceMeta] = []
for sumo_meta in sumo_surface_dir:
surface_metas.append(_sumo_surface_meta_to_api(sumo_meta))

surface_metas = _sort_by_stratigraphical_order(surface_metas, stratigraphical_names)
surface_metas = _sort_by_stratigraphical_order(sumo_surface_dir, stratigraphical_names)
return surface_metas


def _sumo_surface_meta_to_api(sumo_meta: SumoSurfaceMeta) -> schemas.SurfaceMeta:
return schemas.SurfaceMeta(
stratigraphic_name=sumo_meta.name,
stratigraphic_name_is_official=sumo_meta.is_stratigraphic,
attribute_name=sumo_meta.tagname,
attribute_type=schemas.SurfaceAttributeType(sumo_meta.content.value), # Map SumoContent to SurfaceAttributeType
iso_date_or_interval=sumo_meta.iso_date_or_interval,
is_observation=sumo_meta.is_observation,
value_min=sumo_meta.zmin,
value_max=sumo_meta.zmax,
)


def _sort_by_stratigraphical_order(
surface_metas: List[schemas.SurfaceMeta], stratigraphic_surfaces: List[StratigraphicSurface]
sumo_surface_metas: List[SumoSurfaceMeta], stratigraphic_surfaces: List[StratigraphicSurface]
) -> List[schemas.SurfaceMeta]:
"""Sort the surface meta list by the order they appear in the stratigraphic column.
"""Sort the Sumo surface meta list by the order they appear in the stratigraphic column.
Non-stratigraphical surfaces are appended at the end of the list."""

surface_metas_with_official_strat_name = []
surface_metas_with_custom_names = []

for strat_surface in stratigraphic_surfaces:
for surface_meta in surface_metas:
if surface_meta.stratigraphic_name == strat_surface.name:
surface_meta.stratigraphic_name_is_official = True
surface_meta.stratigraphic_feature = strat_surface.feature
for sumo_surface_meta in sumo_surface_metas:
if sumo_surface_meta.name == strat_surface.name:
surface_meta = schemas.SurfaceMeta(
stratigraphic_name=sumo_surface_meta.name,
is_observation=sumo_surface_meta.is_observation,
iso_date_or_interval=sumo_surface_meta.iso_date_or_interval,
value_min=sumo_surface_meta.zmin,
value_max=sumo_surface_meta.zmax,
stratigraphic_name_is_official=True,
stratigraphic_feature=strat_surface.feature,
relative_stratigraphic_level=strat_surface.relative_strat_unit_level,
stratigraphic_unit_parent=strat_surface.strat_unit_parent,
stratigraphic_identifier=strat_surface.strat_unit_identifier,
attribute_name=sumo_surface_meta.tagname,
attribute_type=schemas.SurfaceAttributeType(sumo_surface_meta.content.value),
)
surface_metas_with_official_strat_name.append(surface_meta)

# Append non-official strat names
for surface_meta in surface_metas:
if surface_meta.stratigraphic_name not in [
s.stratigraphic_name for s in surface_metas_with_official_strat_name
]:
surface_meta.stratigraphic_name_is_official = False
for sumo_surface_meta in sumo_surface_metas:
if sumo_surface_meta.name not in [s.stratigraphic_name for s in surface_metas_with_official_strat_name]:
surface_meta = schemas.SurfaceMeta(
stratigraphic_name=sumo_surface_meta.name,
is_observation=sumo_surface_meta.is_observation,
iso_date_or_interval=sumo_surface_meta.iso_date_or_interval,
value_min=sumo_surface_meta.zmin,
value_max=sumo_surface_meta.zmax,
stratigraphic_name_is_official=False,
stratigraphic_feature=None,
relative_stratigraphic_level=0,
stratigraphic_unit_parent=None,
stratigraphic_identifier=None,
attribute_name=sumo_surface_meta.tagname,
attribute_type=schemas.SurfaceAttributeType(sumo_surface_meta.content.value),
)

surface_metas_with_custom_names.append(surface_meta)

return surface_metas_with_official_strat_name + surface_metas_with_custom_names
7 changes: 4 additions & 3 deletions backend/src/backend/primary/routers/surface/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from src.services.sumo_access.surface_access import SurfaceAccess
from src.services.sumo_access.case_inspector import CaseInspector
from src.services.smda_access.stratigraphy_access import StratigraphyAccess
from src.services.smda_access.stratigraphy_utils import sort_stratigraphic_names_by_hierarchy
from src.services.smda_access.mocked_drogon_smda_access import _mocked_stratigraphy_access
from src.services.utils.statistic_function import StatisticFunction
from src.services.utils.authenticated_user import AuthenticatedUser
Expand Down Expand Up @@ -43,10 +44,10 @@ def get_surface_directory(
strat_access = _mocked_stratigraphy_access.StratigraphyAccess(authenticated_user.get_smda_access_token())
else:
strat_access = StratigraphyAccess(authenticated_user.get_smda_access_token())
strat_units = strat_access.get_stratigraphic_units(strat_column_identifier)
sorted_stratigraphic_surfaces = sort_stratigraphic_names_by_hierarchy(strat_units)

stratigraphic_names = strat_access.get_stratigraphic_surfaces(strat_column_identifier)

return converters.to_api_surface_directory(sumo_surf_dir, stratigraphic_names)
return converters.to_api_surface_directory(sumo_surf_dir, sorted_stratigraphic_surfaces)


@router.get("/realization_surface_data/")
Expand Down
5 changes: 4 additions & 1 deletion backend/src/backend/primary/routers/surface/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ class SurfaceAttributeType(str, Enum):


class SurfaceMeta(BaseModel):
stratigraphic_name: str
stratigraphic_name: str # Svarte fm. top / Svarte fm. / Svarte fm. base
stratigraphic_identifier: Optional[str] = None # Svarte fm.
stratigraphic_name_is_official: bool
relative_stratigraphic_level: int
stratigraphic_unit_parent: Optional[str] = None
stratigraphic_feature: Optional[StratigraphicFeature] = None # Distinguish between horizon and unit
attribute_name: str
attribute_type: SurfaceAttributeType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from ..types import StratigraphicUnit, StratigraphicSurface
from ..stratigraphy_utils import sort_stratigraphic_names_by_hierarchy, sort_stratigraphic_units_by_hierarchy

STRAT_UNITS = [
DROGON_STRAT_UNITS = [
StratigraphicUnit(
identifier="Valysar Fm.",
top="Valysar Fm. Top",
Expand Down Expand Up @@ -63,9 +63,9 @@ def __init__(self, access_token: str):
# type: ignore
# pylint: disable=unused-argument
def get_stratigraphic_units(self, stratigraphic_column_identifier: str) -> List[StratigraphicUnit]:
return sort_stratigraphic_units_by_hierarchy(STRAT_UNITS)
return sort_stratigraphic_units_by_hierarchy(DROGON_STRAT_UNITS)

# type: ignore
# pylint: disable=unused-argument
def get_stratigraphic_surfaces(self, stratigraphic_column_identifier: str) -> List[StratigraphicSurface]:
return sort_stratigraphic_names_by_hierarchy(STRAT_UNITS)
return sort_stratigraphic_names_by_hierarchy(DROGON_STRAT_UNITS)
17 changes: 3 additions & 14 deletions backend/src/services/smda_access/stratigraphy_access.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
from typing import List

from .queries.get_stratigraphic_units import get_stratigraphic_units
from .types import StratigraphicUnit, StratigraphicSurface
from .stratigraphy_utils import sort_stratigraphic_names_by_hierarchy, sort_stratigraphic_units_by_hierarchy
from .types import StratigraphicUnit


class StratigraphyAccess:
def __init__(self, access_token: str):
self._smda_token = access_token

def get_stratigraphic_units(self, stratigraphic_column_identifier: str) -> List[StratigraphicUnit]:
"""Get stratigraphic units for stratigraphic column in lithostratigraphical order."""
stratigraphic_units = get_stratigraphic_units(self._smda_token, stratigraphic_column_identifier)

sorted_units = sort_stratigraphic_units_by_hierarchy(stratigraphic_units)
return sorted_units

def get_stratigraphic_surfaces(self, stratigraphic_column_identifier: str) -> List[StratigraphicSurface]:
"""Get a flatten list of top/unit/base surface names in lithostratigraphical order"""
stratigraphic_units = get_stratigraphic_units(self._smda_token, stratigraphic_column_identifier)

sorted_units = sort_stratigraphic_names_by_hierarchy(stratigraphic_units)
return sorted_units
"""Get stratigraphic units for a given stratigraphic column"""
return get_stratigraphic_units(self._smda_token, stratigraphic_column_identifier)
44 changes: 37 additions & 7 deletions backend/src/services/smda_access/stratigraphy_utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import logging
from typing import List
from pydantic import BaseModel

from .types import StratigraphicUnit, StratigraphicSurface, StratigraphicFeature

LOGGER = logging.getLogger(__name__)


class HierarchicalStratigraphicUnit(BaseModel):
"""A stratigraphic unit within a hierarchical structure, i.e a multi-level stratigraphical column"""
Expand Down Expand Up @@ -44,7 +47,7 @@ def flatten_hierarchical_structure(units: List[HierarchicalStratigraphicUnit]) -


def flatten_hierarchical_structure_to_surface_name(
units: List[HierarchicalStratigraphicUnit],
units: List[HierarchicalStratigraphicUnit], idx=0
) -> List[StratigraphicSurface]:
"""Flattens the hierarchy of stratigraphic units to a list of stratigraphic surfaces preserving the order.
On Drogon this will result in the following list:
Expand All @@ -62,23 +65,50 @@ def flatten_hierarchical_structure_to_surface_name(

for hierarchical_unit in units:
unit = hierarchical_unit.unit
flattened_list.append(StratigraphicSurface(name=unit.top, feature=StratigraphicFeature.HORIZON))
flattened_list.append(StratigraphicSurface(name=unit.identifier, feature=StratigraphicFeature.ZONE))
flattened_list.extend(flatten_hierarchical_structure_to_surface_name(hierarchical_unit.children))
flattened_list.append(StratigraphicSurface(name=unit.base, feature=StratigraphicFeature.HORIZON))
LOGGER.info(f"Ordered stratigraphic top: {idx * ' '}{unit.top}")
LOGGER.info(f"Ordered stratigraphic identifier: {idx * ' '}{unit.identifier}")
flattened_list.append(
StratigraphicSurface(
name=unit.top,
feature=StratigraphicFeature.HORIZON,
strat_unit_parent=unit.strat_unit_parent,
relative_strat_unit_level=idx,
strat_unit_identifier=unit.identifier,
)
)
flattened_list.append(
StratigraphicSurface(
name=unit.identifier,
feature=StratigraphicFeature.ZONE,
strat_unit_parent=unit.strat_unit_parent,
relative_strat_unit_level=idx,
strat_unit_identifier=unit.identifier,
)
)
flattened_list.extend(flatten_hierarchical_structure_to_surface_name(hierarchical_unit.children, idx=idx + 1))
flattened_list.append(
StratigraphicSurface(
name=unit.base,
feature=StratigraphicFeature.HORIZON,
strat_unit_parent=unit.strat_unit_parent,
relative_strat_unit_level=idx,
strat_unit_identifier=unit.identifier,
)
)
LOGGER.info(f"Ordered stratigraphic base: {idx * ' '}{unit.base}")

return flattened_list


def sort_stratigraphic_names_by_hierarchy(strat_units: List[StratigraphicUnit]) -> List[StratigraphicSurface]:
"""Creates hierarchy then flattens to a list of surfaces."""
"""Get a flatten list of top/unit/base surface names in lithostratigraphical order"""
hierarchical_units = create_hierarchical_structure(strat_units)
sorted_surfaces = flatten_hierarchical_structure_to_surface_name(hierarchical_units)
return sorted_surfaces


def sort_stratigraphic_units_by_hierarchy(strat_units: List[StratigraphicUnit]) -> List[StratigraphicUnit]:
"""Creates hierarchy then flattens to a list of units."""
"""Get stratigraphic units for stratigraphic column in lithostratigraphical order."""
hierarchical_units = create_hierarchical_structure(strat_units)
sorted_units = flatten_hierarchical_structure(hierarchical_units)
return sorted_units
9 changes: 6 additions & 3 deletions backend/src/services/smda_access/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class StratigraphicUnit(BaseModel):
base: str
strat_unit_level: int
strat_unit_type: str
top_age: Optional[int]
top_age: Optional[int | float]
strat_unit_parent: Optional[str]
color_r: int
color_g: int
Expand All @@ -52,10 +52,13 @@ class StratigraphicUnit(BaseModel):
class StratigraphicFeature(str, Enum):
"""The stratigraphic feature of a surface"""

ZONE = "unit"
HORIZON = "horizon"
ZONE = "zone" # identifier
HORIZON = "horizon" # top/base


class StratigraphicSurface(BaseModel):
name: str
feature: StratigraphicFeature
relative_strat_unit_level: int = 0
strat_unit_parent: Optional[str] = None
strat_unit_identifier: Optional[str] = None
5 changes: 2 additions & 3 deletions backend/src/services/sumo_access/surface_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from ._helpers import create_sumo_client_instance
from .surface_types import SurfaceMeta
from .generic_types import SumoContent
from ..utils.date_utils import iso_datetime_to_date, iso_datetime_to_date_interval

LOGGER = logging.getLogger(__name__)

Expand All @@ -40,9 +39,9 @@ def get_surface_directory(self) -> List[SurfaceMeta]:
t_start = surf["data"].get("time", {}).get("t0", {}).get("value", None)
t_end = surf["data"].get("time", {}).get("t1", {}).get("value", None)
if t_start and not t_end:
iso_string_or_time_interval = iso_datetime_to_date(t_start)
iso_string_or_time_interval = t_start
if t_start and t_end:
iso_string_or_time_interval = iso_datetime_to_date_interval(t_start, t_end)
iso_string_or_time_interval = f"{t_start}/{t_end}"

surf_meta = SurfaceMeta(
name=surf["data"]["name"],
Expand Down
12 changes: 0 additions & 12 deletions backend/src/services/utils/date_utils.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
sort_stratigraphic_units_by_hierarchy,
)
from services.smda_access.types import StratigraphicUnit, StratigraphicSurface, StratigraphicFeature
from services.smda_access.mocked_drogon_smda_access._mocked_stratigraphy_access import STRAT_UNITS
from services.smda_access.mocked_drogon_smda_access._mocked_stratigraphy_access import DROGON_STRAT_UNITS


@pytest.mark.parametrize(
"strat_units, expected_output",
[
(STRAT_UNITS, [STRAT_UNITS[3], STRAT_UNITS[0], STRAT_UNITS[1], STRAT_UNITS[2]]),
(
DROGON_STRAT_UNITS,
[DROGON_STRAT_UNITS[3], DROGON_STRAT_UNITS[0], DROGON_STRAT_UNITS[1], DROGON_STRAT_UNITS[2]],
),
],
)
def test_sort_stratigraphic_units_by_hierarchy(
Expand All @@ -26,7 +29,7 @@ def test_sort_stratigraphic_units_by_hierarchy(
"strat_units, expected_output",
[
(
STRAT_UNITS,
DROGON_STRAT_UNITS,
[
StratigraphicSurface(name="VOLANTIS GP. Top", feature=StratigraphicFeature.HORIZON),
StratigraphicSurface(name="VOLANTIS GP.", feature=StratigraphicFeature.ZONE),
Expand Down

0 comments on commit cb750ae

Please sign in to comment.