Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor status and add status messages to SettlementRodMeasurement #29

Merged
merged 1 commit into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Welcome to BAEC Model Generator SDK documentation!
=======================================
==================================================

The `baec` library is created by `CEMS BV <https://cemsbv.nl/>`_ .

Expand Down
17 changes: 16 additions & 1 deletion docs/tree/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,22 @@ Measured Settlement Series
:member-order: bysource

.. automethod:: __init__


.. _statusMessage:

Status Message
--------------

.. autoclass:: baec.measurements.settlement_rod_measurement.StatusMessage
:members:
:inherited-members:
:member-order: bysource

.. automethod:: __init__

.. autoenum:: baec.measurements.settlement_rod_measurement.StatusMessageLevel
:members:

.. _measurementDevice:

Measurement Device
Expand Down
71 changes: 56 additions & 15 deletions src/baec/measurements/io/zbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,68 @@
from baec.measurements.measurement_device import MeasurementDevice
from baec.measurements.settlement_rod_measurement import (
SettlementRodMeasurement,
SettlementRodMeasurementStatus,
StatusMessage,
StatusMessageLevel,
)
from baec.measurements.settlement_rod_measurement_series import (
SettlementRodMeasurementSeries,
)
from baec.project import Project

_STATUS_MAP = {
0: "ok",
1: "ok",
2: "disturbed",
3: "expired",
4: "relocated",
5: "rod_is_extended",
6: "crooked",
7: "deselected",
8: "deselected",
9: "fictional",
10: "unknown",
0: StatusMessage(code=0, description="OK", level=StatusMessageLevel.OK),
1: StatusMessage(code=1, description="OK", level=StatusMessageLevel.OK),
2: StatusMessage(code=2, description="Disturbed", level=StatusMessageLevel.WARNING),
3: StatusMessage(code=3, description="Expired", level=StatusMessageLevel.WARNING),
4: StatusMessage(code=4, description="Relocated", level=StatusMessageLevel.WARNING),
5: StatusMessage(
code=5, description="Rod is extended", level=StatusMessageLevel.INFO
),
6: StatusMessage(code=6, description="Crooked", level=StatusMessageLevel.WARNING),
7: StatusMessage(
code=7, description="Deselected", level=StatusMessageLevel.WARNING
),
8: StatusMessage(
code=8, description="Deselected", level=StatusMessageLevel.WARNING
),
9: StatusMessage(code=9, description="Fictional", level=StatusMessageLevel.WARNING),
}


def _zbase_status_to_message(status: int) -> StatusMessage:
"""
Convert a ZBase status code to a StatusMessage object.
If the status code is not recognized, a default StatusMessage object is returned
with level set to StatusMessageLevel.ERROR.

Parameters
----------
status : int
The ZBase status code.

Returns
-------
status_message : StatusMessage
The corresponding StatusMessage object.

Raises
------
TypeError
If status is not of type int.
"""
if not isinstance(status, int):
raise TypeError(f"status must be of type `int`, but got {type(status)}.")

status_message = _STATUS_MAP.get(status)
if status_message is None:
status_message = StatusMessage(
code=status,
description="Unrecognized status code",
level=StatusMessageLevel.ERROR,
)
return status_message


def measurements_from_zbase(
filepath_or_buffer: str | PathLike[str] | ReadCsvBuffer[bytes] | ReadCsvBuffer[str],
project_name: str,
Expand Down Expand Up @@ -98,6 +138,7 @@ def measurements_from_zbase(
# create SettlementRodMeasurement objects
measurements = []
for _, row in df.iterrows():
status = row.get("status")
measurements.append(
SettlementRodMeasurement(
project=Project(id_=id_, name=project_name),
Expand All @@ -113,9 +154,9 @@ def measurements_from_zbase(
rod_length=row.get("rod_top_z", 0) - row.get("rod_bottom_z", 0),
rod_bottom_z=row.get("rod_bottom_z", 0),
ground_surface_z=row.get("ground_surface_z", 0),
status=SettlementRodMeasurementStatus(
_STATUS_MAP.get(row.get("status", 10), "unknown")
),
status_messages=[]
if status is None
else [_zbase_status_to_message(status)],
)
)

Expand Down
32 changes: 32 additions & 0 deletions src/baec/measurements/measured_settlement.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import datetime
from functools import cache, cached_property
from typing import List

from baec.measurements.settlement_rod_measurement import (
SettlementRodMeasurement,
SettlementRodMeasurementStatus,
StatusMessage,
)
from baec.project import Project

Expand All @@ -29,6 +31,7 @@ def __init__(
horizontal_units: str,
vertical_units: str,
status: SettlementRodMeasurementStatus,
status_messages: List[StatusMessage],
) -> None:
"""
Initializes a MeasuredSettlement object.
Expand Down Expand Up @@ -63,6 +66,9 @@ def __init__(
status: SettlementRodMeasurementStatus
The status of the settlement rod measurement from which the measured settlement
is derived.
status_messages: List[StatusMessage]
The list of status messages about the settlement rod measurement from which the
measured settlement is derived.

Raises
------
Expand All @@ -86,6 +92,7 @@ def __init__(
self._set_horizontal_units(horizontal_units)
self._set_vertical_units(vertical_units)
self._set_status(status)
self._set_status_messages(status_messages)

@classmethod
def from_settlement_rod_measurement(
Expand Down Expand Up @@ -156,6 +163,7 @@ def from_settlement_rod_measurement(
horizontal_units=measurement.coordinate_reference_systems.horizontal_units,
vertical_units=measurement.coordinate_reference_systems.vertical_units,
status=measurement.status,
status_messages=measurement.status_messages,
)

def _set_project(self, value: Project) -> None:
Expand Down Expand Up @@ -274,6 +282,21 @@ def _set_status(self, value: SettlementRodMeasurementStatus) -> None:
)
self._status = value

def _set_status_messages(self, value: List[StatusMessage]) -> None:
"""
Private setter for status attribute.
"""
if not isinstance(value, list):
raise TypeError(
"Expected 'List[StatusMessage]' type for 'status_messages' attribute."
)
# Check if the input is a list of StatusMessage objects.
if not all(isinstance(item, StatusMessage) for item in value):
raise TypeError(
"Expected 'List[StatusMessage]' type for 'status_messages' attribute."
)
self._status_messages = value

@property
def project(self) -> Project:
"""
Expand Down Expand Up @@ -364,6 +387,14 @@ def status(self) -> SettlementRodMeasurementStatus:
"""
return self._status

@property
def status_messages(self) -> List[StatusMessage]:
"""
The list of status messages about the settlement rod measurement from which the
measured settlement is derived.
"""
return self._status_messages

@cache
def to_dict(self) -> dict:
"""
Expand All @@ -383,4 +414,5 @@ def to_dict(self) -> dict:
"horizontal_units": self.horizontal_units,
"vertical_units": self.vertical_units,
"status": self.status.value,
"status_messages": "\n".join([m.to_string() for m in self.status_messages]),
}
18 changes: 10 additions & 8 deletions src/baec/measurements/measured_settlement_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,18 +139,20 @@ def __init__(
If the `start_index` is out of range for the series.
"""

# Check the types of the input parameters.
if not isinstance(series, SettlementRodMeasurementSeries):
raise TypeError(
"Expected 'SettlementRodMeasurementSeries' type for 'series' parameter."
)

# set SettlementRodMeasurementSeries
self._series = series
self._set_series(series)

# set start of settlement
self._set_start_index_or_start_date_time(start_index, start_date_time)

def _set_series(self, value: SettlementRodMeasurementSeries) -> None:
"""Private setter for series attribute."""
if not isinstance(value, SettlementRodMeasurementSeries):
raise TypeError(
"Expected 'SettlementRodMeasurementSeries' type for 'series' attribute."
)
self._series = value

def _set_start_index_or_start_date_time(
self,
start_index: int | None = None,
Expand Down Expand Up @@ -438,7 +440,7 @@ def to_dataframe(self) -> pd.DataFrame:
A pandas DataFrame with the measured settlements. The columns of the DataFrame are:
project_id, project_name, object_id, start_date_time
date_time, days, fill_thickness, settlement, x_displacement, y_displacement
horizontal_units, vertical_units, status
horizontal_units, vertical_units, status, status_messages
"""
return pd.DataFrame.from_records(
[measurement.to_dict() for measurement in self.items]
Expand Down
Loading
Loading