diff --git a/lib/nexrad/radar.py b/lib/nexrad/radar.py index 037a9fe..8a2e958 100644 --- a/lib/nexrad/radar.py +++ b/lib/nexrad/radar.py @@ -38,6 +38,8 @@ def parse(text: str): return Coord(sign_lat * lat, sign_lon * lon) +RADAR_RANGE = 230000 + class Radar(): __slots__ = 'wban', 'call', 'name', 'coord', 'site_elevation', 'tower_height', diff --git a/lib/nexrad/s3.py b/lib/nexrad/s3.py new file mode 100644 index 0000000..ceecc0f --- /dev/null +++ b/lib/nexrad/s3.py @@ -0,0 +1,74 @@ +import re +import datetime + +S3_BUCKET = 'noaa-nexrad-level2' +S3_KEY_RE = re.compile(r'^(\d{4})/(\d{2})/(\d{2})/([A-Z]{4})/([A-Z]{4})(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})[_\.]') + +def key_matches(key: str, + start: datetime.datetime, + end: datetime.datetime): + match = S3_KEY_RE.match(key) + + if match is None: + return False + + date = datetime.datetime( + year = int(match[6]), + month = int(match[7]), + day = int(match[8]), + hour = int(match[9]), + minute = int(match[10]), + second = int(match[11]), + tzinfo = datetime.UTC + ) + + return date >= start and date <= end + +class S3Bucket(): + def __init__(self, s3, name: str=S3_BUCKET): + self.s3 = s3 + self.name = name + self.cache = dict() + + def each_key_by_prefix(self, prefix: str): + if prefix in self.cache: + for key in self.cache[prefix]: + yield key + else: + result = self.s3.list_objects_v2( + Bucket = self.name, + Prefix = prefix + ) + + cache = list() + self.cache[prefix] = cache + + if result is None or 'Contents' not in result: + return + + for item in result['Contents']: + key = item['Key'] + + cache.append(key) + + yield key + + def each_matching_key(self, + radars: list, + start: datetime.datetime, + end: datetime.datetime): + elapsed = end - start + + for radar in radars: + for day in range(0, 1+elapsed.days): + date = start + datetime.timedelta(days=day) + prefix = '%04d/%02d/%02d/%s/' % ( + date.year, + date.month, + date.day, + radar[1] + ) + + for key in self.each_key_by_prefix(prefix): + if key_matches(key, start, end): + yield key diff --git a/lib/nexrad/storm.py b/lib/nexrad/storm.py index 4599e9c..70d99b6 100644 --- a/lib/nexrad/storm.py +++ b/lib/nexrad/storm.py @@ -3,6 +3,7 @@ import csv import datetime from nexrad.coord import Coord, COORD_SYSTEM +from nexrad.radar import RADAR_RANGE def time_from_str(time: str): size = len(time) @@ -124,10 +125,10 @@ class StormReport(): from nexrad_radar where - distance <= 230000 + distance <= {range} order by distance asc - """.format(csr=COORD_SYSTEM) + """.format(csr=COORD_SYSTEM, range=RADAR_RANGE) radars = list()