diff --git a/lib/nexrad/storm.py b/lib/nexrad/storm.py index 6f9a7d7..6ee6488 100644 --- a/lib/nexrad/storm.py +++ b/lib/nexrad/storm.py @@ -2,7 +2,9 @@ import re import gzip import csv import datetime +import shapely +from nexrad.db import DatabaseTable from nexrad.coord import Coord, COORD_SYSTEM from nexrad.radar import RADAR_RANGE @@ -79,25 +81,62 @@ def coord_from_str(text_lon: str, text_lat: str): return Coord(lon, lat) -class StormReport(): +class StormReport(DatabaseTable): __slots__ = ( - 'timestamp_start', 'timestamp_end', 'episode_id', 'event_id', - 'state', 'event_type', 'wfo', 'coord_start', 'coord_end', - 'locale_start', 'locale_end', 'tornado_f_rating' + 'id', 'timestamp_start', 'timestamp_end', 'episode_id', + 'state', 'event_type', 'wfo', 'locale_start', 'locale_end', + 'tornado_f_rating', 'coord_start', 'coord_end' ) + __table__ = 'nexrad_storm_report' + __key__ = 'id' + + __columns__ = ( + 'id', 'timestamp_start', 'timestamp_end', 'episode_id', + 'state', 'event_type', 'wfo', 'locale_start', 'locale_end', + 'tornado_f_rating', 'coord_start', 'coord_end' + ) + + __selectors__ = { + 'coord_start': 'ST_AsText(coord_start) as coord_start', + 'coord_end': 'ST_AsText(coord_end) as coord_end' + } + + id: int timestamp_start: datetime.datetime timestamp_end: datetime.datetime episode_id: int - event_id: int state: str event_type: str wfo: str - coord_start: Coord - coord_end: Coord locale_start: str locale_end: str tornado_f_rating: str + coord_start: Coord + coord_end: Coord + + @staticmethod + def __from_row__(row): + report = StormReport() + + report.id = row['id'] + report.timestamp_start = datetime.datetime.fromisoformat(row['timestamp_start']) + report.timestamp_end = datetime.datetime.fromisoformat(row['timestamp_end']) + report.episode_id = row['episode_id'] + report.state = row['state'] + report.event_type = row['event_type'] + report.wfo = row['wfo'] + report.locale_start = row['locale_start'] + report.locale_end = row['locale_end'] + report.tornado_f_rating = row['tornado_f_rating'] + + c = shapely.from_wkt(row['coord_start']) + report.coord_start = Coord(c.x, c.y) + + c = shapely.from_wkt(row['coord_end']) + report.coord_end = Coord(c.x, c.y) + + return report @staticmethod def from_csv_row(row: dict): @@ -110,11 +149,11 @@ class StormReport(): report.state = row['STATE'] report.event_type = row['EVENT_TYPE'] report.wfo = row['WFO'] - report.coord_start = coord_from_str(row['BEGIN_LON'], row['BEGIN_LAT']) - report.coord_end = coord_from_str(row['END_LON'], row['END_LAT']) report.locale_start = row['BEGIN_LOCATION'] report.locale_end = row['END_LOCATION'] report.tornado_f_rating = row['TOR_F_SCALE'] + report.coord_start = coord_from_str(row['BEGIN_LON'], row['BEGIN_LAT']) + report.coord_end = coord_from_str(row['END_LON'], row['END_LAT']) try: report.episode_id = int(row['EPISODE_ID']) @@ -122,9 +161,9 @@ class StormReport(): report.episode_id = None try: - report.event_id = int(row['EVENT_ID']) + report.id = int(row['EVENT_ID']) except ValueError: - report.event_id = None + report.id = None return report @@ -139,6 +178,45 @@ class StormReport(): except: pass + def add_to_db(self, db): + sql = """ + insert into nexrad_storm_report ( + id, + episode_id, + timestamp_start, + timestamp_end, + state, + event_type, + wfo, + locale_start, + locale_end, + tornado_f_rating, + coord_start, + coord_end + ) values ( + ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, + MakePoint(?, ?, {crs}), + MakePoint(?, ?, {crs}) + ) + """.format(crs=COORD_SYSTEM) + + db.execute(sql, ( + self.id, + self.episode_id, + self.timestamp_start.isoformat(), + self.timestamp_end.isoformat(), + self.state, + self.event_type, + self.wfo, + self.locale_start, + self.locale_end, + self.tornado_f_rating, + self.coord_start.lon, + self.coord_start.lat, + self.coord_end.lon, + self.coord_end.lat + )) + RADAR_SIGNIFICANT_EVENT_TYPES = { 'Blizzard': True, 'Coastal Flood': True, diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..245b632 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +boto3>=1.36 +shapely>=2.0