Tweak SPC outlook parser to ingest all archival products
This commit is contained in:
parent
8f854a78e8
commit
4e2bf52ad2
1 changed files with 33 additions and 15 deletions
|
@ -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
|
||||
#
|
||||
polygons, interiors, linestrings = convert_segments(segments)
|
||||
try:
|
||||
polygons, interiors, linestrings = convert_segments(segments)
|
||||
except shapely.errors.TopologicalError:
|
||||
return
|
||||
except shapely.errors.GEOSException:
|
||||
return
|
||||
|
||||
#
|
||||
# We do our winding logic now
|
||||
|
@ -203,7 +208,11 @@ def each_poly(parts: list[str]):
|
|||
polygons[i] = polygon.buffer(0)
|
||||
|
||||
for polygon in polygons:
|
||||
yield polygon
|
||||
if polygon.geom_type == 'MultiPolygon':
|
||||
for poly in polygon.geoms:
|
||||
yield poly
|
||||
else:
|
||||
yield polygon
|
||||
|
||||
class SPCOutlookArea(DatabaseTable):
|
||||
__slots__ = ('id', 'outlook_id', 'poly')
|
||||
|
@ -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
|
||||
else:
|
||||
area.probability = float(self.category)
|
||||
area.sig = False
|
||||
|
||||
self.outlook.probabilities.append(area)
|
||||
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:
|
||||
self.parse_validity(line)
|
||||
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:
|
||||
|
|
Loading…
Add table
Reference in a new issue