Skip to content

Commit

Permalink
feat(light_records.py): Changed the LightRecord concept from a "span"…
Browse files Browse the repository at this point in the history
… to a single "state change".
  • Loading branch information
rbeyer committed Oct 14, 2023
1 parent 65a548f commit 7f55f42
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 51 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ and the release date, in year-month-day format (see examples below).
Unreleased
----------

Changed
^^^^^^^
- The light_records.py table now just records state changes (from 'on' to 'off' or
vice-versa).

Added
^^^^^
- yamcs_reception_time column added to the image_records.py table.
Expand Down
47 changes: 18 additions & 29 deletions src/vipersci/vis/db/light_records.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
# top level of this library.

from sqlalchemy import (
Boolean,
DateTime,
Identity,
Integer,
Expand All @@ -51,7 +52,8 @@

class LightRecord(Base):
"""An object to represent rows in the light_records table for VIS. Each row
represents a single 'on' period for one light."""
represents a single state change (from 'on' to 'off' or vice-versa) for one
light."""

# This class is derived from SQLAlchemy's orm.DeclarativeBase
# which means that it has a variety of class properties that are
Expand All @@ -73,17 +75,18 @@ class LightRecord(Base):
name = mapped_column(
String, nullable=False, doc="The luminaire that was activated."
)
start_time = mapped_column(
DateTime(timezone=True),
on = mapped_column(
Boolean,
nullable=False,
doc="The time at which the luminaire was first measured to be on "
"(measuredState = ON).",
doc="If this light, at this time, turned 'on', this column is TRUE, if the "
"this light was detected to go from ON to OFF at this time, this column is "
"FALSE.",
)
last_time = mapped_column(
datetime = mapped_column(
DateTime(timezone=True),
nullable=True,
doc="The last time which the luminaire was measured to be on "
"(measuredState = ON).",
nullable=False,
doc="The time at which the luminaire was first measured to change state "
"(via measuredState) from ON to OFF or vice-versa.",
)

@validates("name")
Expand All @@ -97,24 +100,10 @@ def validate_name(self, key, value):
)
return value

@validates(
"start_time",
"last_time",
)
def validate_datetime_asutc(self, key, value):
dt = vld.validate_datetime_asutc(key, value)
if key == "start_time" and self.last_time is not None:
if dt > self.last_time:
raise ValueError(
f"The start_time ({dt}) must be before the "
f"last_time ({self.last_time})."
)

if key == "last_time" and self.start_time is not None:
if dt < self.start_time:
raise ValueError(
f"The start_time ({self.start_time}) must be before the "
f"last_time ({dt})."
)
@validates("on")
def validate_on(self, key, value):
return bool(value)

return dt
@validates("datetime")
def validate_datetime_asutc(self, key, value):
return vld.validate_datetime_asutc(key, value)
28 changes: 19 additions & 9 deletions src/vipersci/vis/pds/create_raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
# top level of this library.

import argparse
from datetime import date
from datetime import date, timedelta
from importlib import resources
import json
import logging
Expand Down Expand Up @@ -249,15 +249,25 @@ def main():

def get_lights(ir: ImageRecord, session: Session):
lights = {k: False for k in luminaire_names.values()}
stmt = select(LightRecord).where(
and_(
LightRecord.start_time < ir.start_time,
ir.start_time < LightRecord.last_time,
for light in lights:
prev_stmt = (
select(LightRecord)
.where(
and_(
LightRecord.name == light,
LightRecord.datetime < ir.start_time,
)
)
.order_by(LightRecord.datetime.desc())
)
)
result = session.scalars(stmt)
for row in result.all():
lights[row.name] = True
prev_light = session.scalars(prev_stmt).first()

if (
prev_light is not None
and prev_light.on
and ir.start_time - prev_light.datetime < timedelta(seconds=10)
):
lights[light] = True

return lights

Expand Down
35 changes: 32 additions & 3 deletions tests/test_create_raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,41 @@ def test_get_lights(self):
li = cr.get_lights(self.ir, self.session)
self.assertEqual(truth, li)

# Add a light
# Add an early light
self.session.add(
LightRecord(
name=light_name,
start_time="2023-11-25T14:04:10Z",
last_time="2023-11-25T14:04:20Z",
on=True,
datetime="2023-11-25T13:04:10Z",
)
)
early = cr.get_lights(self.ir, self.session)
self.assertEqual(truth, early)

# A previous light "off" event w/in 10 s
self.session.add(
LightRecord(
name=light_name,
on=False,
datetime="2023-11-25T13:04:09Z",
)
)
off = cr.get_lights(self.ir, self.session)
self.assertEqual(truth, off)

# Add a light "on" w/in 10 s:
self.session.add(
LightRecord(
name=light_name,
on=True,
datetime="2023-11-25T14:04:10Z",
)
)
self.session.add(
LightRecord(
name=light_name,
on=False,
datetime="2023-11-25T14:04:20Z",
)
)
truth[light_name] = True
Expand Down
18 changes: 8 additions & 10 deletions tests/test_light_records.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,13 @@

class TestLights(unittest.TestCase):
def setUp(self):
self.t1 = datetime(2023, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
self.t2 = datetime(2023, 1, 1, 0, 0, 8, tzinfo=timezone.utc)
self.t3 = datetime(2023, 1, 1, 0, 0, 12, tzinfo=timezone.utc)
self.dt = datetime(2023, 1, 1, 0, 0, 0, tzinfo=timezone.utc)

def test_init(self):
good = lr.LightRecord(
name="navLeft",
start_time=self.t1,
last_time=self.t2,
on=True,
datetime=self.dt,
)
self.assertEqual(good.name, "NavLight Left")

Expand All @@ -49,14 +47,14 @@ def test_init_fail(self):
ValueError,
lr.LightRecord,
name="not a name",
start_time=self.t1,
last_time=self.t2,
on=False,
datetime=self.dt,
)

self.assertRaises(
ValueError,
lr.LightRecord,
name="not a name",
start_time=self.t3,
last_time=self.t2,
name="navRight",
on=True,
datetime="not a datetime",
)

0 comments on commit 7f55f42

Please sign in to comment.