diff --git a/lib/xmet/raob.py b/lib/xmet/raob.py index 8b26a8b..c55a8fc 100644 --- a/lib/xmet/raob.py +++ b/lib/xmet/raob.py @@ -121,7 +121,7 @@ class RAOBObs(): ) def parse_temp_dewpoint(self, token: str): - if token[2] == '/': + if token[2] == '/' or token[0:4] == 'NNNN': return { 'temp': None, 'dewpoint': None @@ -130,6 +130,7 @@ class RAOBObs(): if token[0:2] == '//': temp = None else: + print(f"Got token {token}") tenths = int(token[2]) sign = 1 if tenths % 2 == 0 else -1 @@ -138,7 +139,11 @@ class RAOBObs(): if token[3:5] == '//': dewpoint = None else: - dda = int(token[3:5]) + if token[4] == '/': + dda = int(token[3]) + else: + dda = int(token[3:5]) + dd = dda * 0.1 if dda <= 50 else dda - 50 dewpoint = temp - dd @@ -151,12 +156,6 @@ class RAOBObs(): base_speed = 0 base_dir = 0 - if token == '=' or token == '//END': - return { - 'dir': None, - 'speed': None - } - if token[2] != '/': value = int(token[2]) @@ -267,16 +266,23 @@ class RAOBObs(): } def parse_pressure(self, token: str): - code, pressure = token[0:2], float(token[2:5]) - - if pressure < 100: - pressure += 1000.0 - - return { - 'pressure': pressure if code in self.PRESSURE_CODES else None, + ret = { + 'pressure': None, 'height': None } + code, pressure = token[0:2], token[2:5] + + if pressure != '///' and code in self.PRESSURE_CODES: + value = float(pressure) + + if value < 100: + value += 1000.0 + + ret['pressure'] = value + + return ret + def parse_ttaa_sample(self, tokens: list[str]) -> dict: sample = SoundingSample() @@ -320,7 +326,7 @@ class RAOBObs(): samples = list() for i in range(2, len(self.tokens), 3): - if len(self.tokens) < i+3 or self.tokens[i][-1] == '=': + if len(self.tokens) < i+3: break # @@ -329,10 +335,10 @@ class RAOBObs(): if self.tokens[i][0:2] == '88': break - data = self.parse_ttaa_sample(self.tokens[i:i+3]) + sample = self.parse_ttaa_sample(self.tokens[i:i+3]) - if data is not None: - samples.append(data) + if sample is not None: + samples.append(sample) return { 'station': station, @@ -351,12 +357,12 @@ class RAOBObs(): } def parse_ttbb(self) -> dict: - station = self.tokens[1] - timestamp = self.tokens[2] + station = self.tokens[0] + timestamp = self.tokens[1] samples = list() - for i in range(3, len(self.tokens), 2): - samples.append(self.parse_sample_tokens(self.tokens[i:i+2])) + for i in range(2, len(self.tokens), 2): + samples.append(self.parse_ttbb_sample(self.tokens[i:i+2])) return { 'station': station, @@ -368,10 +374,10 @@ class RAOBChunk(): def __init__(self, wfo: str, product: str, - tokens: list[str]): + lines: list[str]): self.wfo = wfo self.product = product - self.tokens = tokens + self.lines = lines def is_obs_start(self, token: str) -> bool: return token == 'TTAA' or token == 'TTBB' \ @@ -382,27 +388,43 @@ class RAOBChunk(): def each_obs(self): obs = None - for token in self.tokens: - if self.is_obs_start(token): - if obs is not None: - yield obs + for line in self.lines: + tokens = re.split(r'\s+', line.rstrip()) - obs = RAOBObs(token) - elif obs is not None: - obs.read(token) + for token in tokens: + if obs is None: + if self.is_obs_start(token): + obs = RAOBObs(token) + else: + if token == '//END': + yield obs + obs = None + else: + i = token.find('=') + + if i < 0: + obs.read(token) + else: + obs.read(token[0:i]) + yield obs + obs = None if obs is not None: yield obs def each_data(self): for obs in self.each_obs(): + data = None + if obs.kind == 'TTAA': data = obs.parse_ttaa() + elif obs.kind == 'TTBB': + data = obs.parse_ttbb() - if data is None or len(data['samples']) == 0: - continue + if data is None or len(data['samples']) == 0: + continue - yield data + yield data class RAOBReader(): """ @@ -480,18 +502,7 @@ class RAOBReader(): meta['product'] = match['product'] line_index += 1 - # - # Split each whitespace-delimited column of each line into one big - # list of lines for the remainder of the current text chunk. - # - tokens = list() - - for line in lines[line_index:]: - tokens.extend(re.split(r'\s+', line)) - - return RAOBChunk(meta['wfo'], - meta['product'], - tokens) + return RAOBChunk(meta['wfo'], meta['product'], lines) def each_chunk(self): for text in each_chunk(self.fh, CHUNK_SEP, CHUNK_STRIP_CHARS): @@ -509,15 +520,15 @@ class RAOBReader(): for data in samples: pressure = data['pressure'] - sounding.record_height(pressure, data['height']) + sounding.record_height(pressure, data.get('height')) sounding.record_temp_dewpoint(pressure, - data['temp'], - data['dewpoint']) + data.get('temp'), + data.get('dewpoint')) sounding.record_wind_speed_dir(pressure, - data['wind_speed'], - data['wind_dir']) + data.get('wind_speed'), + data.get('wind_dir')) for key in self.soundings: yield self.soundings[key].finish()