Improve RAOB parsing
This commit is contained in:
parent
e119657309
commit
db22113c55
1 changed files with 63 additions and 52 deletions
115
lib/xmet/raob.py
115
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()
|
||||
|
|
Loading…
Add table
Reference in a new issue