Tweak SPC outlook parser to ingest all archival products

This commit is contained in:
XANTRONIX 2025-04-05 18:30:43 -04:00
parent 8f854a78e8
commit 4e2bf52ad2

View file

@ -25,9 +25,9 @@ RE_HEADER = re.compile(r'''
\s+ (?P<day>\d+)
\s+ CONVECTIVE
\s+ OUTLOOK
''', re.X)
''', re.IGNORECASE | re.X)
RE_OFFICE = re.compile(r'.* STORM PREDICTION CENTER .*')
RE_OFFICE = re.compile(r'.*STORM PREDICTION CENTER.*')
RE_ISSUANCE = re.compile(r'''
^(?P<hour>\d{2})
@ -38,7 +38,7 @@ RE_ISSUANCE = re.compile(r'''
\s+ (?P<month>[A-Z]{3})
\s+ (?P<day>\d{2})
\s+ (?P<year>\d{4})$
''', re.X)
''', re.IGNORECASE | re.X)
RE_VALIDITY = re.compile(r'''
^VALID \s+ TIME
@ -49,7 +49,7 @@ RE_VALIDITY = re.compile(r'''
\s+ (?P<day_end>\d{2})
(?P<hour_end>\d{2})
(?P<minute_end>\d{2})Z$
''', re.X)
''', re.IGNORECASE | re.X)
RE_AREA_TYPE = re.compile(r'^(?P<type>[A-Z ]+) OUTLOOK POINTS DAY .*')
@ -57,14 +57,14 @@ RE_HAZARD = re.compile(r'''
^(?:\.\.\.)
\s+ (?P<type>[A-Z ]+)
\s+ (?:\.\.\.)$
''', re.X)
''', re.IGNORECASE | re.X)
RE_POINTS_START = re.compile(r'''
^(?P<category>[A-Z0-9\.]+)
(?P<rest>(?:\s+\d{8}){1,6})
''', re.X)
''', re.IGNORECASE | re.X)
RE_POINTS = re.compile(r'^(?:\s+\d{8}){1,6}$')
RE_POINTS = re.compile(r'^(?:\s+\d{8}){1,6}$', re.IGNORECASE)
CITIES = {
'CA': (
@ -174,7 +174,12 @@ def each_poly(parts: list[str]):
#
# 3. Convert segments into what they are
#
try:
polygons, interiors, linestrings = convert_segments(segments)
except shapely.errors.TopologicalError:
return
except shapely.errors.GEOSException:
return
#
# We do our winding logic now
@ -203,6 +208,10 @@ def each_poly(parts: list[str]):
polygons[i] = polygon.buffer(0)
for polygon in polygons:
if polygon.geom_type == 'MultiPolygon':
for poly in polygon.geoms:
yield poly
else:
yield polygon
class SPCOutlookArea(DatabaseTable):
@ -408,7 +417,7 @@ class SPCOutlookParser():
day_start = int(match['day_start'])
day_end = int(match['day_end'])
if day_start > day_end:
if day_start > day_end and month_end == 12:
month_end = (month_end + 1) % 12
if month_start > month_end:
@ -446,11 +455,16 @@ class SPCOutlookParser():
if self.category == 'SIGN':
area.probability = None
area.sig = True
self.outlook.probabilities.append(area)
else:
try:
area.probability = float(self.category)
area.sig = False
self.outlook.probabilities.append(area)
except ValueError:
pass
elif self.area_type == 'CATEGORICAL':
area = SPCOutlookCategoryArea()
area.category = self.category
@ -540,7 +554,11 @@ class SPCOutlookParser():
elif self.state is SPCOutlookParserState.ISSUANCE:
self.parse_issuance(line)
elif self.state is SPCOutlookParserState.VALIDITY:
try:
self.parse_validity(line)
except SPCOutlookParserException:
self.outlook.timestamp_start = self.outlook.timestamp_issued
self.outlook.timestamp_end = self.outlook.timestamp_issued + datetime.timedelta(days = 1)
elif self.state is SPCOutlookParserState.AREA_THREAT:
self.parse_area_hazard(line)
elif self.state is SPCOutlookParserState.BODY: