Compare commits
3 commits
ff0891f345
...
8bea18af4d
Author | SHA1 | Date | |
---|---|---|---|
8bea18af4d | |||
650718a00b | |||
2f15dea8c4 |
2 changed files with 78 additions and 25 deletions
|
@ -25,7 +25,9 @@ class RAOBSounding():
|
||||||
def __init__(self, station: str, timestamp: str):
|
def __init__(self, station: str, timestamp: str):
|
||||||
self.station = station
|
self.station = station
|
||||||
self.timestamp = timestamp
|
self.timestamp = timestamp
|
||||||
self.samples = dict()
|
|
||||||
|
self.samples_by_pressure = dict()
|
||||||
|
self.samples_by_height = dict()
|
||||||
|
|
||||||
def parse_timestamp(self, token: str):
|
def parse_timestamp(self, token: str):
|
||||||
if token[0:2] == '//':
|
if token[0:2] == '//':
|
||||||
|
@ -58,14 +60,25 @@ class RAOBSounding():
|
||||||
sounding.timestamp_observed = timestamp
|
sounding.timestamp_observed = timestamp
|
||||||
sounding.timestamp_released = timestamp - datetime.timedelta(minutes=45)
|
sounding.timestamp_released = timestamp - datetime.timedelta(minutes=45)
|
||||||
|
|
||||||
for pressure in sorted(self.samples.keys(), reverse=True):
|
seen = dict()
|
||||||
sounding.samples.append(self.samples[pressure])
|
|
||||||
|
for pressure in sorted(self.samples_by_pressure.keys(), reverse=True):
|
||||||
|
sample = self.samples_by_pressure[pressure]
|
||||||
|
seen[sample] = True
|
||||||
|
|
||||||
|
sounding.samples.append(sample)
|
||||||
|
|
||||||
|
for height in sorted(self.samples_by_height.keys()):
|
||||||
|
sample = self.samples_by_height[height]
|
||||||
|
|
||||||
|
if sample not in seen:
|
||||||
|
sounding.samples.append(sample)
|
||||||
|
|
||||||
return sounding
|
return sounding
|
||||||
|
|
||||||
def sample(self, pressure: float):
|
def sample_by_pressure(self, pressure: float):
|
||||||
if pressure in self.samples:
|
if pressure in self.samples_by_pressure:
|
||||||
return self.samples[pressure]
|
return self.samples_by_pressure[pressure]
|
||||||
|
|
||||||
sample = SoundingSample()
|
sample = SoundingSample()
|
||||||
sample.pressure = pressure
|
sample.pressure = pressure
|
||||||
|
@ -73,19 +86,42 @@ class RAOBSounding():
|
||||||
sample.height_qa = ' '
|
sample.height_qa = ' '
|
||||||
sample.temp_qa = ' '
|
sample.temp_qa = ' '
|
||||||
|
|
||||||
self.samples[pressure] = sample
|
self.samples_by_pressure[pressure] = sample
|
||||||
|
|
||||||
|
return sample
|
||||||
|
|
||||||
|
def sample_by_height(self, height: float):
|
||||||
|
if height in self.samples_by_height:
|
||||||
|
return self.samples_by_height[height]
|
||||||
|
|
||||||
|
sample = SoundingSample()
|
||||||
|
sample.height = height
|
||||||
|
sample.pressure_qa = ' '
|
||||||
|
sample.height_qa = ' '
|
||||||
|
sample.temp_qa = ' '
|
||||||
|
|
||||||
|
self.samples_by_height[height] = sample
|
||||||
|
|
||||||
return sample
|
return sample
|
||||||
|
|
||||||
def record_height(self, pressure: float, height: float):
|
def record_height(self, pressure: float, height: float):
|
||||||
sample = self.sample(pressure)
|
if height is None or pressure is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
sample = self.sample_by_pressure(pressure)
|
||||||
sample.height = height
|
sample.height = height
|
||||||
|
|
||||||
|
if height not in self.samples_by_height:
|
||||||
|
self.samples_by_height[height] = sample
|
||||||
|
|
||||||
def record_temp_dewpoint(self,
|
def record_temp_dewpoint(self,
|
||||||
pressure: float,
|
pressure: float,
|
||||||
temp: float,
|
temp: float,
|
||||||
dewpoint: float):
|
dewpoint: float):
|
||||||
sample = self.sample(pressure)
|
if pressure is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
sample = self.sample_by_pressure(pressure)
|
||||||
sample.temp = temp
|
sample.temp = temp
|
||||||
sample.dewpoint = dewpoint
|
sample.dewpoint = dewpoint
|
||||||
|
|
||||||
|
@ -93,7 +129,10 @@ class RAOBSounding():
|
||||||
pressure: float,
|
pressure: float,
|
||||||
wind_speed: float,
|
wind_speed: float,
|
||||||
wind_dir: float):
|
wind_dir: float):
|
||||||
sample = self.sample(pressure)
|
if pressure is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
sample = self.sample_by_pressure(pressure)
|
||||||
sample.wind_speed = wind_speed
|
sample.wind_speed = wind_speed
|
||||||
sample.wind_dir = wind_dir
|
sample.wind_dir = wind_dir
|
||||||
|
|
||||||
|
@ -373,21 +412,29 @@ class RAOBObs():
|
||||||
}
|
}
|
||||||
|
|
||||||
def parse_ppbb_samples(self, tokens: list[str]) -> dict:
|
def parse_ppbb_samples(self, tokens: list[str]) -> dict:
|
||||||
|
ret = dict()
|
||||||
|
|
||||||
heights = tokens[0]
|
heights = tokens[0]
|
||||||
|
|
||||||
if heights[0] != '9':
|
if heights[0] != '9':
|
||||||
return dict()
|
return dict()
|
||||||
|
|
||||||
|
if heights[1] != '/':
|
||||||
tens = int(heights[1])
|
tens = int(heights[1])
|
||||||
h1 = 0.3048 * (10000 * tens) + (1000 * int(heights[2]))
|
|
||||||
h2 = 0.3048 * (10000 * tens) + (1000 * int(heights[3]))
|
|
||||||
h3 = 0.3048 * (10000 * tens) + (1000 * int(heights[4]))
|
|
||||||
|
|
||||||
return {
|
if len(heights) > 1 and heights[2] != '/' and len(tokens) > 1:
|
||||||
h1: self.parse_wind(tokens[1]),
|
h = 0.3048 * (10000 * tens) + (1000 * int(heights[2]))
|
||||||
h2: self.parse_wind(tokens[2]),
|
ret[h] = self.parse_wind(tokens[1])
|
||||||
h3: self.parse_wind(tokens[3])
|
|
||||||
}
|
if len(heights) > 2 and heights[3] != '/' and len(tokens) > 2:
|
||||||
|
h = 0.3048 * (10000 * tens) + (1000 * int(heights[3]))
|
||||||
|
ret[h] = self.parse_wind(tokens[2])
|
||||||
|
|
||||||
|
if len(heights) > 3 and heights[4] != '/' and len(tokens) > 3:
|
||||||
|
h = 0.3048 * (10000 * tens) + (1000 * int(heights[4]))
|
||||||
|
ret[h] = self.parse_wind(tokens[3])
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
def parse_ppbb(self) -> dict:
|
def parse_ppbb(self) -> dict:
|
||||||
timestamp = self.tokens[0]
|
timestamp = self.tokens[0]
|
||||||
|
@ -460,6 +507,8 @@ class RAOBChunk():
|
||||||
data = obs.parse_ttaa()
|
data = obs.parse_ttaa()
|
||||||
elif obs.kind == 'TTBB':
|
elif obs.kind == 'TTBB':
|
||||||
data = obs.parse_ttbb()
|
data = obs.parse_ttbb()
|
||||||
|
elif obs.kind == 'PPBB':
|
||||||
|
data = obs.parse_ppbb()
|
||||||
|
|
||||||
if data is None or len(data['samples']) == 0:
|
if data is None or len(data['samples']) == 0:
|
||||||
continue
|
continue
|
||||||
|
@ -558,10 +607,13 @@ class RAOBReader():
|
||||||
sounding = self.sounding(station, timestamp)
|
sounding = self.sounding(station, timestamp)
|
||||||
|
|
||||||
for data in samples:
|
for data in samples:
|
||||||
pressure = data['pressure']
|
pressure = data.get('pressure')
|
||||||
|
height = data.get('height')
|
||||||
|
|
||||||
if pressure is None:
|
if pressure is None and height is not None:
|
||||||
continue
|
sample = sounding.sample_by_height(height)
|
||||||
|
sample.wind_speed = data.get('wind_speed')
|
||||||
|
sample.wind_dir = data.get('wind_dir')
|
||||||
|
|
||||||
sounding.record_height(pressure, data.get('height'))
|
sounding.record_height(pressure, data.get('height'))
|
||||||
|
|
||||||
|
|
|
@ -54,9 +54,10 @@ class SoundingSample(DatabaseTable):
|
||||||
self.wind_speed: float = None
|
self.wind_speed: float = None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
parts = [
|
parts = list()
|
||||||
("%.2fmb" % self.pressure)
|
|
||||||
]
|
if self.pressure is not None:
|
||||||
|
parts.append("%.2fmb" % self.pressure)
|
||||||
|
|
||||||
if self.height is not None:
|
if self.height is not None:
|
||||||
parts.append("%.1fm" % self.height)
|
parts.append("%.1fm" % self.height)
|
||||||
|
|
Loading…
Add table
Reference in a new issue