diff --git a/lib/xmet/spc.py b/lib/xmet/spc.py index 9f17bd1..9a0beb7 100644 --- a/lib/xmet/spc.py +++ b/lib/xmet/spc.py @@ -25,9 +25,9 @@ RE_HEADER = re.compile(r''' \s+ (?P\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\d{2}) @@ -38,7 +38,7 @@ RE_ISSUANCE = re.compile(r''' \s+ (?P[A-Z]{3}) \s+ (?P\d{2}) \s+ (?P\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\d{2}) (?P\d{2}) (?P\d{2})Z$ -''', re.X) +''', re.IGNORECASE | re.X) RE_AREA_TYPE = re.compile(r'^(?P[A-Z ]+) OUTLOOK POINTS DAY .*') @@ -57,14 +57,14 @@ RE_HAZARD = re.compile(r''' ^(?:\.\.\.) \s+ (?P[A-Z ]+) \s+ (?:\.\.\.)$ -''', re.X) +''', re.IGNORECASE | re.X) RE_POINTS_START = re.compile(r''' ^(?P[A-Z0-9\.]+) (?P(?:\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: