diff --git a/lib/nexrad/storm.py b/lib/nexrad/storm.py index e83ae9a..9094ead 100644 --- a/lib/nexrad/storm.py +++ b/lib/nexrad/storm.py @@ -102,6 +102,11 @@ class StormReport(DatabaseTable): 'coord_end': 'ST_AsText(coord_end) as coord_end' } + __constructors__ = { + 'coord_start': lambda v: 'null' if v is None else f'MakePoint({v.lon}, {v.lat}, {COORD_SYSTEM})', + 'coord_end': lambda v: 'null' if v is None else f'MakePoint({v.lon}, {v.lat}, {COORD_SYSTEM})' + } + id: int timestamp_start: datetime.datetime timestamp_end: datetime.datetime @@ -130,11 +135,17 @@ class StormReport(DatabaseTable): 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) + try: + c = shapely.from_wkt(row['coord_start']) + report.coord_start = Coord(c.x, c.y) + except: + report.coord_start = None - c = shapely.from_wkt(row['coord_end']) - report.coord_end = Coord(c.x, c.y) + try: + c = shapely.from_wkt(row['coord_end']) + report.coord_end = Coord(c.x, c.y) + except: + report.coord_end = None return report @@ -178,44 +189,48 @@ class StormReport(DatabaseTable): except: pass - def add_to_db(self, db): + @staticmethod + def each_matching(db, + coord: Coord=None, + radius: float=RADAR_RANGE, + timestamp: datetime.datetime=None): 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) + select * from nexrad_storm_report + """ - 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 - )) + clauses = list() + values = list() + + if coord is not None: + clauses.append("""ST_DistanceWithin(MakeLine(coord_start, coord_end), + MakePoint(?, ?, {csr}), + {radius}) = 1""".format( + csr = COORD_SYSTEM, + radius = radius + )) + + values.append(coord.lon) + values.append(coord.lat) + + if timestamp is not None: + clauses.append("timestamp_start >= ? and timestamp_end <= ?") + + values.append(timestamp.isoformat()) + + if len(clauses) > 0: + sql += " where " + " and ".join(clauses) + + print(f"Got query {sql} coord {coord.lat}, {coord.lon}") + + st = db.query_sql(StormReport, sql, values) + + while True: + obj = st.fetchone() + + if obj is None: + break + + yield obj RADAR_SIGNIFICANT_EVENT_TYPES = { 'Blizzard': True,