Skip to content

Commit e5d0e00

Browse files
committed
feat: transfer sensors and deployments
1 parent a41f1f4 commit e5d0e00

4 files changed

Lines changed: 121 additions & 19 deletions

File tree

.pre-commit-config.yaml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ repos:
1515
'--statistics'
1616
]
1717
exclude: ^db/__init__.py$ # all models need to be imported for Alembic, but are not used directly
18-
# - repo: local
19-
# hooks:
20-
# - id: pytest
21-
# name: pytest
22-
# entry: pytest # Or your specific test command, e.g., poetry run pytest
23-
# language: system
24-
# types: [python] # Specify relevant file types for your tests
25-
# pass_filenames: false
26-
# always_run: true
18+
- repo: local
19+
hooks:
20+
- id: pytest
21+
name: pytest
22+
entry: pytest # Or your specific test command, e.g., poetry run pytest
23+
language: system
24+
types: [python] # Specify relevant file types for your tests
25+
pass_filenames: false
26+
always_run: true
2727

2828
# - repo: https://github.com/pre-commit/mirrors-mypy
2929
# rev: v1.10.0 # Use the latest stable version or pin to your preference

db/deployment.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ class Deployment(Base, AutoBaseMixin, ReleaseMixin):
3737
removal_date: Mapped[Date] = mapped_column(Date, nullable=True)
3838
recording_interval: Mapped[int] = mapped_column(Integer, nullable=True)
3939
recording_interval_units: Mapped[str] = lexicon_term(nullable=True)
40-
hanging_cable_length: Mapped[float] = mapped_column(Numeric, nullable=True)
40+
hanging_cable_length: Mapped[float] = mapped_column(
41+
Numeric,
42+
nullable=True,
43+
comment="Length of cable from sensor to hanging point, in ft",
44+
)
4145
hanging_point_height: Mapped[float] = mapped_column(Numeric, nullable=True)
4246
hanging_point_description: Mapped[str] = mapped_column(Text, nullable=True)
4347
notes: Mapped[str] = mapped_column(Text, nullable=True)

transfers/sensor_transfer.py

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,106 @@
1414
# limitations under the License.
1515
# ===============================================================================
1616
from datetime import datetime
17+
import pandas as pd
1718

18-
from db import Sensor
19+
from db import Sensor, Deployment, Thing
20+
from transfers.util import read_csv, logger
21+
22+
EQUIPMENT_TO_SENSOR_TYPE_MAP = {
23+
"Pressure transducer": "Pressure Transducer",
24+
"Acoustic sounder": "Acoustic Sounder",
25+
"Barometer": "Barometer",
26+
}
27+
28+
29+
def transfer_sensors(session):
30+
equipment = read_csv("Equipment")
31+
equipment.columns = equipment.columns.str.replace(" ", "_")
32+
grouped_equipment = equipment.groupby(["PointID"])
33+
34+
for index, group in grouped_equipment:
35+
pointid = index[0]
36+
thing = session.query(Thing).filter(Thing.name == pointid).first()
37+
if thing is None:
38+
logger.warning(
39+
f"Skipping sensor transfer for Thing with PointID {pointid} since it is not in the DB"
40+
)
41+
continue
42+
ordered_group = group.sort_values(by=["DateInstalled"])
43+
44+
if pointid == "SO-0168":
45+
print(ordered_group)
46+
47+
try:
48+
for row in ordered_group.itertuples():
49+
if row.EquipmentType not in EQUIPMENT_TO_SENSOR_TYPE_MAP:
50+
logger.critical(
51+
f"Skipping equipment with type {row.EquipmentType} for point {pointid}"
52+
)
53+
continue
54+
55+
sensor = (
56+
session.query(Sensor)
57+
.filter(Sensor.serial_no == row.SerialNo)
58+
.one_or_none()
59+
)
60+
if sensor:
61+
logger.info(
62+
f"Sensor with serial number {row.SerialNo} already exists. Only creating deployment for that record"
63+
)
64+
else:
65+
sensor = Sensor(
66+
nma_pk_equipment=row.GlobalID,
67+
name=row.ID,
68+
sensor_type=EQUIPMENT_TO_SENSOR_TYPE_MAP[row.EquipmentType],
69+
model=row.Model,
70+
serial_no=row.SerialNo,
71+
owner_agency="NMBGMR",
72+
notes=row.Equipment_Notes,
73+
)
74+
session.add(sensor)
75+
logger.info(
76+
f"Added sensor {sensor.name} with serial number {sensor.serial_no}"
77+
)
78+
79+
installation_date = datetime.strptime(
80+
row.DateInstalled, "%Y-%m-%d %H:%M:%S.%f"
81+
).date()
82+
removal_date = (
83+
datetime.strptime(row.DateRemoved, "%Y-%m-%d %H:%M:%S.%f").date()
84+
if not pd.isna(row.DateRemoved)
85+
else None
86+
)
87+
deployment = Deployment(
88+
thing=thing,
89+
sensor=sensor,
90+
installation_date=installation_date,
91+
removal_date=removal_date,
92+
recording_interval=int(row.RecordingInterval),
93+
recording_interval_units="hour",
94+
hanging_cable_length=row.HangingCableLength,
95+
hanging_point_height=row.HangingPointHgt,
96+
hanging_point_description=row.HangingPointDescription,
97+
)
98+
session.add(deployment)
99+
logger.info(
100+
f"Added deployment for sensor with serial number {sensor.serial_no}, deployed to {thing.name}: | Installation Date: {installation_date} | Removal Date: {removal_date}"
101+
)
102+
103+
"""
104+
Developer's notes
105+
106+
Since it's unclear beforehand if a sensor has been removed just update
107+
the sensor_status based off of each deployments installation/removal
108+
dates
109+
"""
110+
if installation_date:
111+
sensor.sensor_status = "In Service"
112+
if removal_date:
113+
sensor.sensor_status = "Retired"
114+
session.commit()
115+
except Exception as e:
116+
logger.critical(f"Could not add sensor and deployment: {e}")
19117

20118

21119
# ============= EOF =============================================
@@ -27,3 +125,7 @@ def init_sensor(session):
27125
sensor.datetime_installed = datetime.now()
28126
session.add(sensor)
29127
session.commit()
128+
129+
130+
if __name__ == "__main__":
131+
transfer_sensors("abc")

transfers/transfer.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from transfers.group_transfer import transfer_groups
2929
from transfers.link_ids_transfer import transfer_link_ids, transfer_link_ids_welldata
3030
from transfers.contact_transfer import transfer_contacts
31-
from transfers.sensor_transfer import init_sensor
31+
from transfers.sensor_transfer import transfer_sensors
3232
from transfers.waterlevels_transfer import transfer_water_levels
3333
from transfers.well_transfer import (
3434
transfer_wells,
@@ -54,13 +54,6 @@ def erase_and_initalize(session: Session) -> None:
5454
erase(session)
5555
lexicon()
5656
parameter()
57-
sensor(session)
58-
59-
60-
@timeit
61-
def sensor(session: Session):
62-
logger.info("Initializing sensors")
63-
init_sensor(session)
6457

6558

6659
@timeit
@@ -125,6 +118,9 @@ def transfer_all(sess, limit=100):
125118
message("TRANSFERRING METEOROLOGICAL")
126119
timeit_direct(transfer_met, sess, limit)
127120

121+
message("TRANSFERRING SENSORS")
122+
timeit_direct(transfer_sensors, sess)
123+
128124
message("TRANSFERRING CONTACTS")
129125
timeit_direct(transfer_contacts, sess)
130126

0 commit comments

Comments
 (0)