def make_skewt_axes(self,pmax=1050.,pmin=100.,tmin=-40.,tmax=30.): """Set up the skew-t axis the way I like to see it""" self.fig = figure(figsize=(8,8)) self.fig.clf() rcParams.update({\ 'font.size':10,\ }) self.skewxaxis=self.fig.add_axes([.065,.1,.71,.8], projection='skewx') self.skewxaxis.set_yscale('log') self.skewxaxis.pmax=pmax self.skewxaxis.pmin=pmin self.skewxaxis.tmax=tmax self.skewxaxis.tmin=tmin xticklocs=arange(-80,45,10) T0 = xticklocs # P=linspace(pmax,pmin,101) P=logspace(log10(pmax),log10(pmin),101) w = array([0.00001,0.0001,0.0004,0.001, 0.002, 0.004, 0.007, 0.01, 0.016, 0.024, 0.032]) self.skewxaxis.add_mixratio_isopleths(w,P[P>=700],color='g',ls='--',alpha=1.,lw=0.5) self.skewxaxis.add_dry_adiabats(linspace(210,550,18)-degCtoK,P,color='g',ls='--',alpha=1.,lw=0.5) self.skewxaxis.add_moist_adiabats(linspace(0,44,12),pmax,color='g',ls='--',alpha=1.,lw=0.5) #self.skewxaxis.add_moist_adiabats(linspace(0,38,12),pmax,color='g',ls='--',alpha=1.,lw=0.5) self.skewxaxis.set_title("%s %s"%(self['StationNumber'],self['SoundingDate'])) self.skewxaxis.other_housekeeping() self.wbax=self.fig.add_axes([0.685,0.1,0.1,0.8],sharey=self.skewxaxis,frameon=False) self.wbax.xaxis.set_ticks([],[]) self.wbax.yaxis.grid(True,ls='-',color='y',lw=0.5) for tick in self.wbax.yaxis.get_major_ticks(): # tick.label1On = False pass self.wbax.get_yaxis().set_tick_params(size=0,color='y') self.wbax.set_xlim(-1.5,1.5) self.wbax.get_yaxis().set_visible(False) self.wbax.set_title('kn',fontsize=10,color='k',ha='right') # Set up standard atmosphere height scale on # LHS of plot. majorLocatorKM = MultipleLocator(2) majorLocatorKFT = MultipleLocator(5) minorLocator = MultipleLocator(1) # determine base height from base pressure (nominally 1050 hPa) # via hydrostatic equilibrium for standard atmosphere # model atmospheric conditions with constant lapse rate and # NIST (1013.25hPa and 20C) zmin=barometric_equation_inv(0,293.15,101325.,pmax*100.) zmax=barometric_equation_inv(0,293.15,101325.,pmin*100.) zminf=zmin*3.2808 zmaxf=zmax*3.2808 self.kmhax=self.fig.add_axes([0.775,0.1,1e-6,0.8],frameon=True) self.kmhax.xaxis.set_ticks([],[]) self.kmhax.spines['left'].set_color('k') self.kmhax.spines['right'].set_visible(False) self.kmhax.tick_params(axis='y', colors='k',labelsize=8) self.kmhax.set_ylim(zmin*1e-3,zmax*1e-3) self.kmhax.set_title("km/kft",fontsize=10) self.kmhax.get_yaxis().set_tick_params(which="both",direction='out') self.kmhax.yaxis.set_major_locator(majorLocatorKM) self.kmhax.yaxis.set_minor_locator(minorLocator) self.fthax=self.kmhax.twinx() self.fthax.xaxis.set_ticks([],[]) self.fthax.tick_params(axis='y', colors='k',labelsize=8) self.fthax.set_ylim(zminf*1e-3,zmaxf*1e-3) self.fthax.get_yaxis().set_tick_params(which="both",direction='out') self.fthax.yaxis.set_major_locator(majorLocatorKFT) self.fthax.yaxis.set_minor_locator(minorLocator)
def make_skewt_axes(self, pmax=1050., pmin=100., tmin=-40., tmax=30., fig=None): """Set up the skew-t axis the way I like to see it""" if fig is None: self.fig = figure(figsize=(8, 8)) # self.fig.clf() else: self.fig = fig rcParams.update({'font.size': 10, }) self.skewxaxis = self.fig.add_axes([.065, .1, .71, .8], projection='skewx') self.skewxaxis.set_yscale('log') self.skewxaxis.pmax = pmax self.skewxaxis.pmin = pmin self.skewxaxis.tmax = tmax self.skewxaxis.tmin = tmin xticklocs = arange(-80, 45, 10) T0 = xticklocs # P=linspace(pmax,pmin,101) P = logspace(log10(pmax), log10(pmin), 101) w = array([0.00001, 0.0001, 0.0004, 0.001, 0.002, 0.004, 0.007, 0.01, 0.016, 0.024, 0.032]) self.skewxaxis.add_mixratio_isopleths( w, P[P >= 700], color='g', ls='--', alpha=1., lw=0.5) self.skewxaxis.add_dry_adiabats( linspace(210, 550, 18)-degCtoK, P, color='g', ls='--', alpha=1., lw=0.5) self.skewxaxis.add_moist_adiabats( linspace(0, 44, 12), pmax, color='g', ls='--', alpha=1., lw=0.5) self.skewxaxis.set_title("%s %s" % (self['StationNumber'], self['SoundingDate'])) self.skewxaxis.other_housekeeping() self.wbax = self.fig.add_axes([0.685, 0.1, 0.1, 0.8], sharey=self.skewxaxis, frameon=False) self.wbax.xaxis.set_ticks([], []) self.wbax.yaxis.grid(True, ls='-', color='y', lw=0.5) for tick in self.wbax.yaxis.get_major_ticks(): # tick.label1On = False pass self.wbax.get_yaxis().set_tick_params(size=0, color='y') self.wbax.set_xlim(-1.5, 1.5) self.wbax.get_yaxis().set_visible(False) self.wbax.set_title('kn', fontsize=10, color='k', ha='right') # Set up standard atmosphere height scale on # LHS of plot. majorLocatorKM = MultipleLocator(2) majorLocatorKFT = MultipleLocator(5) minorLocator = MultipleLocator(1) # determine base height from base pressure (nominally 1050 hPa) # via hydrostatic equilibrium for standard atmosphere # model atmospheric conditions with constant lapse rate and # NIST (1013.25hPa and 20C) zmin = barometric_equation_inv(0, 293.15, 101325., pmax*100.) zmax = barometric_equation_inv(0, 293.15, 101325., pmin*100.) zminf = zmin * 3.2808 zmaxf = zmax * 3.2808 self.kmhax = self.fig.add_axes([0.775, 0.1, 1e-6, 0.8], frameon=True) self.kmhax.xaxis.set_ticks([], []) self.kmhax.spines['left'].set_color('k') self.kmhax.spines['right'].set_visible(False) self.kmhax.tick_params(axis='y', colors='k', labelsize=8) self.kmhax.set_ylim(zmin*1e-3, zmax*1e-3) self.kmhax.set_title("km/kft", fontsize=10) self.kmhax.get_yaxis().set_tick_params(which="both", direction='out') self.kmhax.yaxis.set_major_locator(majorLocatorKM) self.kmhax.yaxis.set_minor_locator(minorLocator) self.fthax = self.kmhax.twinx() self.fthax.xaxis.set_ticks([], []) self.fthax.tick_params(axis='y', colors='k', labelsize=8) self.fthax.set_ylim(zminf*1e-3, zmaxf*1e-3) self.fthax.get_yaxis().set_tick_params(which="both", direction='out') self.fthax.yaxis.set_major_locator(majorLocatorKFT) self.fthax.yaxis.set_minor_locator(minorLocator)
def emit_ascents(args, source, file, archive, raob, stations, updated_stations): relTime, sondTyp, staLat, staLon, staElev, P, T, Td, U, V, wmo_ids, times = RemNaN_and_Interp( raob, file) for i, stn in enumerate(wmo_ids): if args.station and args.station != stn: continue if stn in stations: station = stations[stn] if isnan(staLat[i]): staLat[i] = station['lat'] if isnan(staLon[i]): staLon[i] = station['lon'] if isnan(staElev[i]): staElev[i] = station['elevation'] else: station = None if isnan(staLat[i]) or isnan(staLon[i]) or isnan(staElev[i]): logging.error(f"skipping station {stn} - no location") continue #print(i, stn) takeoff = datetime.utcfromtimestamp( relTime[i]).replace(tzinfo=pytz.utc) syntime = times[i] properties = { "station_id": stn, "id_type": "wmo", "source": "netCDF", "sonde_type": int(sondTyp[i]), "path_source": "simulated", "syn_timestamp": syntime.timestamp(), "firstSeen": float(relTime[i]), "lat": float(staLat[i]), "lon": float(staLon[i]), "elevation": float(staElev[i]), } fc = geojson.FeatureCollection([]) fc.properties = properties lat_t = staLat[i] lon_t = staLon[i] previous_elevation = fc.properties['elevation'] - 100 # args.hstep t0 = T[i][0] p0 = P[i][0] h0 = staElev[i] prevSecsIntoFlight = 0 for n in range(0, len(P[i])): pn = P[i][n] if isinf(T[i][n]) or isinf(Td[i][n]) or isinf(P[i][n]): logging.debug( f"station {stn}: skipping layer P={P[i][n]} T={T[i][n]} Td={Td[i][n]}" ) continue # gross haque to determine rough time of sample height = round(barometric_equation_inv(h0, t0, p0, pn), 1) secsIntoFlight = height2time(h0, height) delta = timedelta(seconds=secsIntoFlight) sampleTime = takeoff + delta properties = { "time": sampleTime.timestamp(), "gpheight": round(height_to_geopotential_height(height), 1), "temp": round(T[i][n], 2), "dewpoint": round(Td[i][n], 2), "pressure": P[i][n], } u = U[i][n] v = V[i][n] du = dv = 0 if u > -9999.0 and v > -9999.0: properties["wind_u"] = u properties["wind_v"] = v dt = secsIntoFlight - prevSecsIntoFlight du = u * dt dv = v * dt lat_t, lon_t = latlonPlusDisplacement(lat=lat_t, lon=lon_t, u=du, v=dv) prevSecsIntoFlight = secsIntoFlight #print(f"level={n} s={secsIntoFlight:.0f} {height:.1f}m p={pn} lon_t={lon_t} lat_t={lat_t} u={u} v={v} du={du:.1f} dv={dv:.1f} ", file=sys.stderr) f = geojson.Feature(geometry=geojson.Point( (float(lon_t), float(lat_t), height)), properties=properties) if not f.is_valid: logging.error(f'--- invalid GeoJSON! {f.errors()}') fc.features.append(f) fc.properties['lastSeen'] = sampleTime.timestamp() write_geojson(args, source, fc, file, archive, updated_stations) return True
def commit_sonde(raob, stations): relTime, sondTyp, staLat, staLon, staElev, P, T, Td, U, V, wmo_ids, times = RemNaN_and_Interp( raob) #print(staElev) for i, stn in enumerate(wmo_ids): if stn in stations: station = stations[stn] # print(f"---- station {stn} found: {station}") if isnan(staLat[i]): staLat[i] = station['lat'] if isnan(staLon[i]): staLon[i] = station['lon'] if isnan(staElev[i]): staElev[i] = station['elevation'] else: # print(f"station {stn} not found") station = None if isnan(staLat[i]) or isnan(staLon[i]) or isnan(staElev[i]): continue #print(i, stn) takeoff = datetime.utcfromtimestamp( relTime[i]).replace(tzinfo=pytz.utc) syntime = times[i] properties = { "station_id": stn, "id_type": "madis", "sonde_type": int(sondTyp[i]), "path_type": "simulated", "syn_timestamp": syntime.timestamp(), "firstSeen": float(relTime[i]), "lat": float(staLat[i]), "lon": float(staLon[i]), "elevation": float(staElev[i]), } fc = geojson.FeatureCollection([]) fc.properties = properties lat_t = staLat[i] lon_t = staLon[i] firstSeen = fc.properties['firstSeen'] previous_elevation = fc.properties['elevation'] - 100 # args.hstep t0 = T[i][0] p0 = P[i][0] h0 = staElev[i] #print(f"station h0={h0:.1f}m p0={p0} t0={t0}") prevSecsIntoFlight = 0 for n in range(0, len(P[i])): pn = P[i][n] # gross haque to determine rough time of sample height = round(barometric_equation_inv(h0, t0, p0, pn), 1) secsIntoFlight = height2time(h0, height) delta = timedelta(seconds=secsIntoFlight) sampleTime = takeoff + delta properties = { "time": sampleTime.timestamp(), "gpheight": round(height_to_geopotential_height(height), 1), "temp": round(T[i][n], 2), "dewpoint": round(Td[i][n], 2), "pressure": P[i][n], } u = U[i][n] v = V[i][n] du = dv = 0 if u > -9999.0 and v > -9999.0: properties["wind_u"] = u properties["wind_v"] = v dt = secsIntoFlight - prevSecsIntoFlight du = u * dt dv = v * dt lat_t, lon_t = latlonPlusDisplacement(lat=lat_t, lon=lon_t, u=du, v=dv) prevSecsIntoFlight = secsIntoFlight print( f"level={n} s={secsIntoFlight:.0f} {height:.1f}m p={pn} lon_t={lon_t} lat_t={lat_t} u={u} v={v} du={du:.1f} dv={dv:.1f} ", file=sys.stderr) f = geojson.Feature(geometry=geojson.Point( (float(lat_t), float(lon_t), height)), properties=properties) fc.features.append(f) fc.properties['lastSeen'] = sampleTime.timestamp() #print(fc) print(geojson.dumps(fc, indent=4, ignore_nan=True)) sys.exit(0) # for n in range(len(P[i])-1): # print(i, n, stn, T[n], P[n]) # #print(n, P[n])times[i], continue t = datetime.utcfromtimestamp(relTime[i]).replace(tzinfo=pytz.utc) print(i, stn, times[i], t, len(raob['Psig'][i]), len(T[i]), len(P[i])) radiosonde = Radiosonde() radiosonde.sonde_validtime = times[i] radiosonde.temperatureK = T[i] radiosonde.dewpointK = Td[i] radiosonde.pressurehPA = P[i] radiosonde.u_windMS = U[i] radiosonde.v_windMS = V[i]
def make_skewt_axes(self, pmax=1050., pmin=100., tmin=-40., tmax=30.): """Set up the skew-t axis the way I like to see it""" #self.fig = figure(figsize=(3.54,1.8)) self.fig = figure(figsize=(16, 8)) self.fig.clf() self.skewxaxis = self.fig.add_axes([.065, .1, .71, .8], projection='skewx') self.skewxaxis.set_yscale('log') self.skewxaxis.pmax = pmax self.skewxaxis.pmin = pmin self.skewxaxis.tmax = tmax self.skewxaxis.tmin = tmin xticklocs = arange(-80, 45, 10) T0 = xticklocs # P=linspace(pmax,pmin,101) P = logspace(log10(pmax), log10(pmin), 101) w = array([ 0.00001, 0.0001, 0.0004, 0.001, 0.002, 0.004, 0.007, 0.01, 0.016, 0.024, 0.032 ]) w = array([0.001, 0.002, 0.004, 0.007, 0.01, 0.016, 0.024, 0.032]) ## BKB: Dont add mixratio # self.skewxaxis.add_mixratio_isopleths(w,P[P>=550],color='g',ls='--',alpha=1.,lw=0.5) self.skewxaxis.add_dry_adiabats(linspace(210, 550, 18) - degCtoK, P, color='g', ls='--', alpha=1., lw=0.3, do_labels=False) # BKB: Dont add moist adiabat #self.skewxaxis.add_moist_adiabats(linspace(0,44,12),pmax,color='g',ls='--',alpha=1.,lw=0.5) self.skewxaxis.set_title("%s %s" % (self['StationNumber'], self['SoundingDate']), fontsize=15) self.skewxaxis.other_housekeeping() # wind barbs axes self.wbax = self.fig.add_axes([0.685, 0.1, 0.1, 0.8], sharey=self.skewxaxis, frameon=False) self.wbax.xaxis.set_ticks([], []) self.wbax.yaxis.grid(True, ls='-', color='y', lw=0.3) for tick in self.wbax.yaxis.get_major_ticks(): # tick.label1On = False pass self.wbax.get_yaxis().set_tick_params(size=0, color='y') self.wbax.set_xlim(-1.5, 1.5) self.wbax.get_yaxis().set_visible(False) #self.wbax.set_title('m/s',fontsize=7,color='k',ha='right') # Set up standard atmosphere height scale on # LHS of plot. majorLocatorKM = MultipleLocator(2) majorLocatorKFT = MultipleLocator(5) minorLocator = MultipleLocator(1) # determine base height from base pressure (nominally 1050 hPa) # via hydrostatic equilibrium for standard atmosphere # model atmospheric conditions with constant lapse rate and # NIST (1013.25hPa and 20C) zmin = barometric_equation_inv(0, 293.15, 101325., pmax * 100.) zmax = barometric_equation_inv(0, 293.15, 101325., pmin * 100.) zminf = zmin * 3.2808 zmaxf = zmax * 3.2808 """ Turn off Height Plotter (scale thing on the right side)