def test_arrow_projection_list(wind_projection_list): """Test that arrows will be projected when lat/lon lists are provided.""" lat, lon, u, v = wind_projection_list fig = plt.figure() ax = fig.add_subplot(1, 1, 1) stnplot = StationPlot(ax, lon, lat) stnplot.plot_arrow(u, v) assert stnplot.arrows
def create_ornaments(n_ornaments,color='k'): """create ornaments and return the artist.""" ornaments_y=np.random.triangular(3,3.5,24.5,n_ornaments) bounds=get_x_bounds(ornaments_y) ornaments_x=np.random.rand(n_ornaments)*2*bounds-bounds stationplot=StationPlot(ax,ornaments_x,ornaments_y,clip_on=True,fontsize=24) symbols=np.array(list(wx_code_map.values())) wx=symbols[np.random.randint(0,102,n_ornaments)] return stationplot.plot_symbol('c',wx,current_weather,color=color)
def test_scalar_unit_conversion_exception(): """Test that errors are raise if unit conversion is requested on un-united data.""" x_pos = np.array([0]) y_pos = np.array([0]) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) stnplot = StationPlot(ax, x_pos, y_pos) with pytest.raises(ValueError): stnplot.plot_parameter('C', 50, plot_units='degC')
def test_barb_unit_conversion_exception(u, v): """Test that errors are raise if unit conversion is requested on un-united data.""" x_pos = np.array([0]) y_pos = np.array([0]) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) stnplot = StationPlot(ax, x_pos, y_pos) with pytest.raises(ValueError): stnplot.plot_barb(u, v, plot_units='knots')
def test_plot_symbol_fontsize(): """Test changing fontsize in plotting of symbols.""" fig = plt.figure(figsize=(3, 3)) ax = plt.subplot(1, 1, 1) sp = StationPlot(ax, [0], [0], fontsize=8, spacing=32) sp.plot_symbol('E', [92], current_weather) sp.plot_symbol('W', [96], current_weather, fontsize=100) return fig
def test_barb_projection(wind_plot, ccrs): """Test that barbs are properly projected (#598).""" u, v, x, y = wind_plot # Plot and check barbs (they should align with grid lines) fig = plt.figure() ax = fig.add_subplot(1, 1, 1, projection=ccrs.LambertConformal()) ax.gridlines(xlocs=[-120, -105, -90, -75, -60], ylocs=np.arange(24, 55, 6)) sp = StationPlot(ax, x, y, transform=ccrs.PlateCarree()) sp.plot_barb(u, v) return fig
def test_barb_projection_list(): """Test that barbs will be projected when lat/lon lists are provided.""" lat = [38.22, 38.18, 38.25] lon = [-85.76, -85.86, -85.77] u = [1.89778964, -3.83776523, 3.64147732] * units('m/s') v = [1.93480072, 1.31000184, 1.36075552] * units('m/s') fig = plt.figure() ax = fig.add_subplot(1, 1, 1) stnplot = StationPlot(ax, lon, lat) stnplot.plot_barb(u, v) assert stnplot.barbs
def test_arrow_unit_conversion(barbs_units): """Test that arrow units can be converted at plot time (#737).""" x_pos, y_pos, u_wind, v_wind = barbs_units fig = plt.figure() ax = fig.add_subplot(1, 1, 1) stnplot = StationPlot(ax, x_pos, y_pos) stnplot.plot_arrow(u_wind, v_wind, plot_units='knots') ax.set_xlim(-5, 5) ax.set_ylim(-5, 5) return fig
def test_arrow_projection(wind_plot): """Test that arrows are properly projected.""" u, v, x, y = wind_plot # Plot and check barbs (they should align with grid lines) fig = plt.figure() ax = fig.add_subplot(1, 1, 1, projection=ccrs.LambertConformal()) ax.gridlines(xlocs=[-135, -120, -105, -90, -75, -60, -45]) sp = StationPlot(ax, x, y, transform=ccrs.PlateCarree()) sp.plot_arrow(u, v) sp.plot_arrow(u, v) # plot_arrow used twice to hit removal if statement return fig
def test_symbol_pandas_timeseries(): """Test the usage of Pandas DatetimeIndex as a valid `x` input into StationPlot.""" pd.plotting.register_matplotlib_converters() rng = pd.date_range('12/1/2017', periods=5, freq='D') sc = [1, 2, 3, 4, 5] ts = pd.Series(sc, index=rng) fig, ax = plt.subplots() y = np.ones(len(ts.index)) stationplot = StationPlot(ax, ts.index, y, fontsize=12) stationplot.plot_symbol('C', ts, sky_cover) ax.xaxis.set_major_locator(matplotlib.dates.DayLocator()) ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%-d')) return fig
def test_barb_no_default_unit_conversion(): """Test that barbs units are left alone by default (#737).""" x_pos = np.array([0]) y_pos = np.array([0]) u_wind = np.array([3.63767155210412]) * units('m/s') v_wind = np.array([3.63767155210412]) * units('m/s') fig = plt.figure() ax = fig.add_subplot(1, 1, 1) stnplot = StationPlot(ax, x_pos, y_pos) stnplot.plot_barb(u_wind, v_wind) ax.set_xlim(-5, 5) ax.set_ylim(-5, 5) return fig
def test_barb_unit_conversion(): """Test that barbs units can be converted at plot time (#737).""" x_pos = np.array([0]) y_pos = np.array([0]) u_wind = np.array([3.63767155210412]) * units('m/s') v_wind = np.array([3.63767155210412]) * units('m/s') fig = plt.figure() ax = fig.add_subplot(1, 1, 1) stnplot = StationPlot(ax, x_pos, y_pos) stnplot.plot_barb(u_wind, v_wind, plot_units='knots') ax.set_xlim(-5, 5) ax.set_ylim(-5, 5) return fig
def test_barb_projection(): """Test that barbs are properly projected (#598).""" # Test data of all southerly winds v = np.full((5, 5), 10, dtype=np.float64) u = np.zeros_like(v) x, y = np.meshgrid(np.linspace(-120, -60, 5), np.linspace(25, 50, 5)) # Plot and check barbs (they should align with grid lines) fig = plt.figure() ax = fig.add_subplot(1, 1, 1, projection=ccrs.LambertConformal()) ax.gridlines(xlocs=[-135, -120, -105, -90, -75, -60, -45]) sp = StationPlot(ax, x, y, transform=ccrs.PlateCarree()) sp.plot_barb(u, v) return fig
def test_barb_projection(): """Test that barbs are properly projected (#598).""" # Test data of all southerly winds v = np.full((5, 5), 10, dtype=np.float64) u = np.zeros_like(v) x, y = np.meshgrid(np.linspace(-120, -60, 5), np.linspace(25, 50, 5)) # Plot and check barbs (they should align with grid lines) fig = plt.figure() ax = fig.add_subplot(1, 1, 1, projection=ccrs.LambertConformal()) ax.gridlines() sp = StationPlot(ax, x, y, transform=ccrs.PlateCarree()) sp.plot_barb(u, v) return fig
def test_nws_layout(): """Test metpy's NWS layout for station plots.""" fig = plt.figure(figsize=(3, 3)) # testing data x = np.array([1]) y = np.array([2]) data = {'air_temperature': np.array([77]) * units.degF, 'dew_point_temperature': np.array([71]) * units.degF, 'air_pressure_at_sea_level': np.array([999.8]) * units('mbar'), 'eastward_wind': np.array([15.]) * units.knots, 'northward_wind': np.array([15.]) * units.knots, 'cloud_coverage': [7], 'present_weather': [80], 'high_cloud_type': [1], 'medium_cloud_type': [3], 'low_cloud_type': [2], 'visibility_in_air': np.array([5.]) * units.mile, 'tendency_of_air_pressure': np.array([-0.3]) * units('mbar'), 'tendency_of_air_pressure_symbol': [8]} # Make the plot sp = StationPlot(fig.add_subplot(1, 1, 1), x, y, fontsize=12, spacing=16) nws_layout.plot(sp, data) sp.ax.set_xlim(0, 3) sp.ax.set_ylim(0, 3) return fig
def test_simple_layout(): """Test metpy's simple layout for station plots.""" fig = plt.figure(figsize=(9, 9)) # testing data x = np.array([1, 5]) y = np.array([2, 4]) data = { 'air_temperature': np.array([32., 212.]) * units.degF, 'dew_point_temperature': np.array([28., 80.]) * units.degF, 'air_pressure_at_sea_level': np.array([29.92, 28.00]) * units.inHg, 'eastward_wind': np.array([2, 0]) * units.knots, 'northward_wind': np.array([0, 5]) * units.knots, 'cloud_coverage': [3, 8], 'present_weather': [65, 75], 'unused': [1, 2] } # Make the plot sp = StationPlot(fig.add_subplot(1, 1, 1), x, y, fontsize=12) simple_layout.plot(sp, data) sp.ax.set_xlim(0, 6) sp.ax.set_ylim(0, 6) return fig
def test_stationlayout_api(): """Test the StationPlot API.""" fig = plt.figure(figsize=(9, 9)) # testing data x = np.array([1, 5]) y = np.array([2, 4]) data = {'temp': np.array([32., 212.]) * units.degF, 'u': np.array([2, 0]) * units.knots, 'v': np.array([0, 5]) * units.knots, 'stid': ['KDEN', 'KSHV'], 'cover': [3, 8]} # Set up the layout layout = StationPlotLayout() layout.add_barb('u', 'v', units='knots') layout.add_value('NW', 'temp', fmt='0.1f', units=units.degC, color='darkred') layout.add_symbol('C', 'cover', sky_cover, color='magenta') layout.add_text((0, 2), 'stid', color='darkgrey') layout.add_value('NE', 'dewpt', color='green') # This should be ignored # Make the plot sp = StationPlot(fig.add_subplot(1, 1, 1), x, y, fontsize=12) layout.plot(sp, data) sp.ax.set_xlim(0, 6) sp.ax.set_ylim(0, 6) return fig
def test_plot_text_fontsize(): """Test changing fontsize in plot_text.""" fig = plt.figure(figsize=(3, 3)) ax = plt.subplot(1, 1, 1) # testing data x = np.array([1]) y = np.array([2]) # Make the plot sp = StationPlot(ax, x, y, fontsize=36) sp.plot_text('NW', ['72'], fontsize=24) sp.plot_text('SW', ['60'], fontsize=4) sp.ax.set_xlim(0, 3) sp.ax.set_ylim(0, 3) return fig
def test_station_plot_locations(): """Test that locations are properly replaced.""" fig = plt.figure(figsize=(3, 3)) locations = ['C', 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N2', 'NNE', 'ENE', 'E2', 'ESE', 'SSE', 'S2', 'SSW', 'WSW', 'W2', 'WNW', 'NNW'] x_pos = np.array([0]) y_pos = np.array([0]) # Make the plot sp = StationPlot(fig.add_subplot(1, 1, 1), x_pos, y_pos, fontsize=8, spacing=24) for loc in locations: sp.plot_text(loc, [loc]) sp.ax.set_xlim(-2, 2) sp.ax.set_ylim(-2, 2) return fig
def test_stationplot_clipping(): """Test the that clipping can be enabled as a default parameter.""" fig = plt.figure(figsize=(9, 9)) # testing data x = np.array([1, 5]) y = np.array([2, 4]) # Make the plot sp = StationPlot(fig.add_subplot(1, 1, 1), x, y, fontsize=16, clip_on=True) sp.plot_barb([20, 0], [0, -50]) sp.plot_text('E', ['KOKC', 'ICT'], color='blue') sp.plot_parameter('NW', [10.5, 15] * units.degC, color='red') sp.plot_symbol('S', [5, 7], high_clouds, color='green') sp.ax.set_xlim(1, 5) sp.ax.set_ylim(1.75, 4.25) return fig
def test_station_plot_replace(): """Test that locations are properly replaced.""" fig = plt.figure(figsize=(3, 3)) # testing data x = np.array([1]) y = np.array([1]) # Make the plot sp = StationPlot(fig.add_subplot(1, 1, 1), x, y, fontsize=16) sp.plot_barb([20], [0]) sp.plot_barb([5], [0]) sp.plot_parameter('NW', [10.5], color='red') sp.plot_parameter('NW', [20], color='blue') sp.ax.set_xlim(-3, 3) sp.ax.set_ylim(-3, 3) return fig
def test_stationplot_api(): """Test the StationPlot API.""" fig = plt.figure(figsize=(9, 9)) # testing data x = np.array([1, 5]) y = np.array([2, 4]) # Make the plot sp = StationPlot(fig.add_subplot(1, 1, 1), x, y, fontsize=16) sp.plot_barb([20, 0], [0, -50]) sp.plot_text('E', ['KOKC', 'ICT'], color='blue') sp.plot_parameter('NW', [10.5, 15] * units.degC, color='red') sp.plot_symbol('S', [5, 7], high_clouds, color='green') sp.ax.set_xlim(0, 6) sp.ax.set_ylim(0, 6) return fig
def plotStations(self, obs): self.obs = obs print('setting station plot') self.stnPlots = StationPlot(self.axes, self.obs['longitude'], self.obs['latitude'], clip_on=True, transform=self.PlateCarree) print('plotting') self.stationLayout.plot(self.stnPlots, self.obs) self.canvas.draw() print('Done plotting')
def test_stationplot_api(): """Test the StationPlot API.""" fig = plt.figure(figsize=(9, 9)) # testing data x = np.array([1, 5]) y = np.array([2, 4]) # Make the plot sp = StationPlot(fig.add_subplot(1, 1, 1), x, y, fontsize=16) sp.plot_barb([20, 0], [0, -50]) sp.plot_text("E", ["KOKC", "ICT"], color="blue") sp.plot_parameter("NW", [10.5, 15], color="red") sp.plot_symbol("S", [5, 7], high_clouds, color="green") sp.ax.set_xlim(0, 6) sp.ax.set_ylim(0, 6) return fig
def test_station_layout_odd_data(): """Test more corner cases with data passed in.""" fig = plt.figure(figsize=(9, 9)) # Set up test layout layout = StationPlotLayout() layout.add_barb('u', 'v') layout.add_value('W', 'temperature', units='degF') # Now only use data without wind and no units data = {'temperature': [25.]} # Make the plot sp = StationPlot(fig.add_subplot(1, 1, 1), [1], [2], fontsize=12) layout.plot(sp, data) assert True
def radar_plus_obs(station, my_datetime, radar_title=None, bb=None, station_radius=75000., station_layout=simple_layout, field='reflectivity', vmin=None, vmax=None, sweep=0): if radar_title is None: radar_title = 'Area ' radar = get_radar_from_aws(station, my_datetime) # Lets get some geographical context if bb is None: lats = radar.gate_latitude lons = radar.gate_longitude min_lon = lons['data'].min() min_lat = lats['data'].min() max_lat = lats['data'].max() max_lon = lons['data'].max() bb = {'north' : max_lat, 'south' : min_lat, 'east' : max_lon, 'west' : min_lon} else: min_lon = bb['west'] min_lat = bb['south'] max_lon = bb['east'] max_lat = bb['north'] print('min_lat:', min_lat, ' min_lon:', min_lon, ' max_lat:', max_lat, ' max_lon:', max_lon) index_at_start = radar.sweep_start_ray_index['data'][sweep] time_at_start_of_radar = num2date(radar.time['data'][index_at_start], radar.time['units']) pacific = pytz.timezone('US/Central') local_time = pacific.fromutc(time_at_start_of_radar) fancy_date_string = local_time.strftime('%A %B %d at %I:%M %p %Z') print(fancy_date_string) metar_cat = TDSCatalog('http://thredds.ucar.edu/thredds/catalog/nws/metar/ncdecoded/catalog.xml?' 'dataset=nws/metar/ncdecoded/Metar_Station_Data_fc.cdmr') dataset = list(metar_cat.datasets.values())[0] ncss = NCSS(dataset.access_urls["NetcdfSubset"]) query = ncss.query().accept('csv').time(time_at_start_of_radar) query.lonlat_box(north=max_lat, south=min_lat, east=max_lon, west=min_lon) query.variables('air_temperature', 'dew_point_temperature', 'inches_ALTIM', 'wind_speed', 'wind_from_direction', 'cloud_area_fraction', 'weather') data = ncss.get_data(query) lats = data['latitude'][:] lons = data['longitude'][:] tair = data['air_temperature'][:] dewp = data['dew_point_temperature'][:] slp = (data['inches_ALTIM'][:] * units('inHg')).to('mbar') # Convert wind to components u, v = mpcalc.get_wind_components(data['wind_speed'] * units.knot, data['wind_from_direction'] * units.deg) # Need to handle missing (NaN) and convert to proper code cloud_cover = 8 * data['cloud_area_fraction'] cloud_cover[np.isnan(cloud_cover)] = 9 cloud_cover = cloud_cover.astype(np.int) # For some reason these come back as bytes instead of strings stid = [s.decode() for s in data['station']] # Convert the text weather observations to WMO codes we can map to symbols #wx_text = [s.decode('ascii') for s in data['weather']] #wx_codes = np.array(list(to_code(wx_text))) sfc_data = {'latitude': lats, 'longitude': lons, 'air_temperature': tair, 'dew_point_temperature': dewp, 'eastward_wind': u, 'northward_wind': v, 'cloud_coverage': cloud_cover, 'air_pressure_at_sea_level': slp}#, 'present_weather': wx_codes} fig = plt.figure(figsize=(10, 8)) display = pyart.graph.RadarMapDisplayCartopy(radar) lat_0 = display.loc[0] lon_0 = display.loc[1] # Set our Projection projection = cartopy.crs.Mercator(central_longitude=lon_0, min_latitude=min_lat, max_latitude=max_lat) # Call our function to reduce data filter_data(sfc_data, projection, radius=station_radius, sort_key='present_weather') print(sweep) display.plot_ppi_map( field, sweep, colorbar_flag=True, title=radar_title +' area ' + field + ' \n' + fancy_date_string, projection=projection, min_lon=min_lon, max_lon=max_lon, min_lat=min_lat, max_lat=max_lat, vmin=vmin, vmax=vmax) # Mark the radar display.plot_point(lon_0, lat_0, label_text='Radar') # Get the current axes and plot some lat and lon lines gl = display.ax.gridlines(draw_labels=True, linewidth=2, color='gray', alpha=0.5, linestyle='--') gl.xlabels_top = False gl.ylabels_right = False # Make the station plot stationplot = StationPlot(display.ax, sfc_data['longitude'], sfc_data['latitude'], transform=cartopy.crs.PlateCarree(), fontsize=12) station_layout.plot(stationplot, sfc_data) return display, time_at_start_of_radar
def main(): ### START OF USER SETTINGS BLOCK ### # FILE/DATA SETTINGS # file path to input file datafile = '/home/jgodwin/python/sfc_observations/surface_observations.txt' timefile = '/home/jgodwin/python/sfc_observations/validtime.txt' # file path to county shapefile ctyshppath = '/home/jgodwin/python/sfc_observations/shapefiles/counties/countyl010g.shp' # file path to ICAO list icaopath = '/home/jgodwin/python/sfc_observations/icao_list.csv' icaodf = pd.read_csv(icaopath, index_col='STATION') # MAP SETTINGS # map names (doesn't go anywhere (yet), just for tracking purposes) maps = ['CONUS', 'Texas', 'Tropical Atlantic'] # minimum radius allowed between points (in km) radius = [100.0, 50.0, 75.0] # map boundaries (longitude/latitude degrees) west = [-122, -108, -100] east = [-73, -93, -60] south = [23, 25, 10] north = [50, 38, 35] restart_projection = [True, False, True] # use county map? (True/False): warning, counties load slow! usecounties = [False, False, False] # OUTPUT SETTINGS # save directory for output savedir = '/var/www/html/images/' # filenames for output savenames = ['conus.png', 'texas.png', 'atlantic.png'] # TEST MODE SETTINGS test = False # True/False testnum = 5 # which map are you testing? corresponds to index in "maps" above ### END OF USER SETTING SECTION ### # if there are any missing weather codes, add them here wx_code_map.update({ '-RADZ': 59, '-TS': 17, 'VCTSSH': 80, '-SGSN': 77, 'SHUP': 76, 'FZBR': 48, 'FZUP': 76 }) ### READ IN DATA / SETUP MAP ### # read in the valid time file vt = open(timefile).read() # read in the data for i in range(len(maps)): if test and i != testnum: continue with open(datafile) as f: data = pd.read_csv(f,header=0,names=['siteID','lat','lon','elev','slp','temp','sky','dpt','wx','wdr',\ 'wsp'],na_values=-99999) # drop rows with missing winds data = data.dropna(how='any', subset=['wdr', 'wsp']) # remove data not within our domain data = data[(data['lat'] >= south[i]-2.0) & (data['lat'] <= north[i]+2.0) \ & (data['lon'] >= west[i]-2.0) & (data['lon'] <= east[i]+2.0)] # filter data (there seems to be one site always reporting a really anomalous temperature data = data[data['temp'] <= 50] print("Working on %s" % maps[i]) # set up the map projection central longitude/latitude and the standard parallels cenlon = (west[i] + east[i]) / 2.0 cenlat = (south[i] + north[i]) / 2.0 sparallel = cenlat if cenlat > 0: cutoff = -30 flip = False elif cenlat < 0: cutoff = 30 flip = True # create the projection if restart_projection: proj = ccrs.LambertConformal(central_longitude=cenlon, central_latitude=cenlat, standard_parallels=[sparallel], cutoff=cutoff) point_locs = proj.transform_points(ccrs.PlateCarree(), data['lon'].values, data['lat'].values) data = data[reduce_point_density(point_locs, radius[i] * 1000)] # state borders state_boundaries = cfeature.NaturalEarthFeature(category='cultural',\ name='admin_1_states_provinces_lines',scale='50m',facecolor='none') # county boundaries if usecounties[i]: county_reader = shpreader.Reader(ctyshppath) counties = list(county_reader.geometries()) COUNTIES = cfeature.ShapelyFeature(counties, ccrs.PlateCarree()) ### DO SOME CONVERSIONS ### # get the wind components u, v = wind_components(data['wsp'].values * units('knots'), data['wdr'].values * units.degree) # convert temperature from Celsius to Fahrenheit data['temp'] = cToF(data['temp']) data['dpt'] = cToF(data['dpt']) # convert the cloud fraction value into a code of 0-8 (oktas) and compenate for NaN values cloud_frac = (8 * data['sky']) cloud_frac[np.isnan(cloud_frac)] = 10 cloud_frac = cloud_frac.astype(int) # map weather strings to WMO codes (only use first symbol if multiple are present data['wx'] = data.wx.str.split('/').str[0] + '' wx = [ wx_code_map[s.split()[0] if ' ' in s else s] for s in data['wx'].fillna('') ] # get the minimum and maximum temperatures in domain searchdata = data[(data['lat'] >= south[i]) & (data['lat'] <= north[i]) \ & (data['lon'] >= west[i]) & (data['lon'] <= east[i])] min_temp = searchdata.loc[searchdata['temp'].idxmin()] max_temp = searchdata.loc[searchdata['temp'].idxmax()] max_dewp = searchdata.loc[searchdata['dpt'].idxmax()] # look up the site names for the min/max temp locations min_temp_loc = icaoLookup(min_temp['siteID'], icaodf) max_temp_loc = icaoLookup(max_temp['siteID'], icaodf) max_dewp_loc = icaoLookup(max_dewp['siteID'], icaodf) text_str = "Min temp: %.0f F at %s (%s)\nMax temp: %.0f F at %s (%s)\nMax dewpoint: %.0f F at %s (%s)"\ % (min_temp['temp'],min_temp['siteID'],min_temp_loc,\ max_temp['temp'],max_temp['siteID'],max_temp_loc,\ max_dewp['dpt'],max_dewp['siteID'],max_dewp_loc) ### PLOTTING SECTION ### # change the DPI to increase the resolution plt.rcParams['savefig.dpi'] = 255 # create the figure and an axes set to the projection fig = plt.figure(figsize=(20, 10)) ax = fig.add_subplot(1, 1, 1, projection=proj) # add various map elements ax.add_feature(cfeature.LAND, zorder=-1) ax.add_feature(cfeature.OCEAN, zorder=-1) ax.add_feature(cfeature.LAKES, zorder=-1) ax.add_feature(cfeature.COASTLINE, zorder=2, edgecolor='black') ax.add_feature(state_boundaries, edgecolor='black') if usecounties[i]: ax.add_feature(COUNTIES, facecolor='none', edgecolor='gray', zorder=-1) ax.add_feature(cfeature.BORDERS, linewidth=2, edgecolor='black') # set plot bounds ax.set_extent((west[i], east[i], south[i], north[i])) ### CREATE STATION PLOTS ### # lat/lon of the station plots stationplot = StationPlot(ax,data['lon'].values,data['lat'].values,clip_on=True,\ transform=ccrs.PlateCarree(),fontsize=6) # plot the temperature and dewpoint stationplot.plot_parameter('NW', data['temp'], color='red') stationplot.plot_parameter('SW', data['dpt'], color='darkgreen') # plot the SLP using the standard trailing three digits stationplot.plot_parameter( 'NE', data['slp'], formatter=lambda v: format(10 * v, '.0f')[-3:]) # plot the sky condition stationplot.plot_symbol('C', cloud_frac, sky_cover) # plot the present weather stationplot.plot_symbol('W', wx, current_weather) # plot the wind barbs stationplot.plot_barb(u, v, flip_barb=flip) # plot the text of the station ID stationplot.plot_text((2, 0), data['siteID']) # plot the valid time plt.title('Surface Observations valid %s' % vt) # plot the min/max temperature info and draw circle around warmest and coldest obs props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) plt.text(west[i], south[i], text_str, fontsize=12, verticalalignment='top', bbox=props, transform=ccrs.Geodetic()) projx1, projy1 = proj.transform_point(min_temp['lon'], min_temp['lat'], ccrs.Geodetic()) ax.add_patch( matplotlib.patches.Circle(xy=[projx1, projy1], radius=50000, facecolor="None", edgecolor='blue', linewidth=3, transform=proj)) projx2, projy2 = proj.transform_point(max_temp['lon'], max_temp['lat'], ccrs.Geodetic()) ax.add_patch( matplotlib.patches.Circle(xy=[projx2, projy2], radius=50000, facecolor="None", edgecolor='red', linewidth=3, transform=proj)) projx3, projy3 = proj.transform_point(max_dewp['lon'], max_dewp['lat'], ccrs.Geodetic()) ax.add_patch( matplotlib.patches.Circle(xy=[projx3, projy3], radius=30000, facecolor="None", edgecolor='green', linewidth=3, transform=proj)) # save the figure outfile_name = savedir + savenames[i] plt.savefig(outfile_name, bbox_inches='tight') # clear and close everything fig.clear() ax.clear() plt.close(fig) f.close() print("Script finished.")
ax.coastlines(resolution='110m', zorder=2, color='black') ax.add_feature(state_boundaries, edgecolor='black') ax.add_feature(feat.BORDERS, linewidth='2', edgecolor='black') # Set plot bounds ax.set_extent((-118, -73, 23, 50)) # # Here's the actual station plot # # Start the station plot by specifying the axes to draw on, as well as the # lon/lat of the stations (with transform). We also the fontsize to 12 pt. stationplot = StationPlot(ax, data['longitude'], data['latitude'], transform=ccrs.PlateCarree(), fontsize=12) # The layout knows where everything should go, and things are standardized using # the names of variables. So the layout pulls arrays out of `data` and plots them # using `stationplot`. simple_layout.plot(stationplot, data) plt.show() ########################################### # or instead, a custom layout can be used: # Just winds, temps, and dewpoint, with colors. Dewpoint and temp will be plotted # out to Farenheit tenths. Extra data will be ignored
ax.coastlines(resolution='110m', zorder=2, color='black') ax.add_feature(state_boundaries, edgecolor='black') ax.add_feature(feat.BORDERS, linewidth='2', edgecolor='black') # Set plot bounds ax.set_extent((-118, -73, 23, 50)) # # Here's the actual station plot # # Start the station plot by specifying the axes to draw on, as well as the # lon/lat of the stations (with transform). We also the fontsize to 12 pt. stationplot = StationPlot(ax, data['lon'].values, data['lat'].values, clip_on=True, transform=ccrs.PlateCarree(), fontsize=12) # Plot the temperature and dew point to the upper and lower left, respectively, of # the center point. Each one uses a different color. stationplot.plot_parameter('NW', data['air_temperature'], color='red') stationplot.plot_parameter('SW', data['dew_point_temperature'], color='darkgreen') # A more complex example uses a custom formatter to control how the sea-level pressure # values are plotted. This uses the standard trailing 3-digits of the pressure value # in tenths of millibars. stationplot.plot_parameter('NE', data['slp'],
s=30, marker='+', transform=ccrs.PlateCarree(), color='lightgrey', zorder=-1) # Add gridlines for every 5 degree lat/lon ax.gridlines(linestyle='solid', ylocs=range(15, 71, 5), xlocs=range(-150, -49, 5)) # Start the station plot by specifying the axes to draw on, as well as the # lon/lat of the stations (with transform). We also the fontsize to 10 pt. stationplot = StationPlot(ax, df['longitude'].values, df['latitude'].values, clip_on=True, transform=ccrs.PlateCarree(), fontsize=10) # Plot the temperature and dew point to the upper and lower left, respectively, of # the center point. stationplot.plot_parameter('NW', df['temperature'], color='black') stationplot.plot_parameter('SW', df['dewpoint'], color='black') # A more complex example uses a custom formatter to control how the geopotential height # values are plotted. This is set in an earlier if-statement to work appropriate for # different levels. stationplot.plot_parameter('NE', df['height'], formatter=hght_format) # Add wind barbs stationplot.plot_barb(df['u_wind'], df['v_wind'], length=7, pivot='tip')
ax.add_feature(cfeature.OCEAN) ax.add_feature(cfeature.LAKES) ax.add_feature(cfeature.COASTLINE) ax.add_feature(cfeature.STATES) ax.add_feature(cfeature.BORDERS) # Set plot bounds ax.set_extent((-118, -73, 23, 50)) # # Here's the actual station plot # # Start the station plot by specifying the axes to draw on, as well as the # lon/lat of the stations (with transform). We also the fontsize to 12 pt. stationplot = StationPlot(ax, data['lon'].values, data['lat'].values, clip_on=True, transform=ccrs.PlateCarree(), fontsize=12) # Plot the temperature and dew point to the upper and lower left, respectively, of # the center point. Each one uses a different color. stationplot.plot_parameter('NW', data['air_temperature'], color='red') stationplot.plot_parameter('SW', data['dew_point_temperature'], color='darkgreen') # A more complex example uses a custom formatter to control how the sea-level pressure # values are plotted. This uses the standard trailing 3-digits of the pressure value # in tenths of millibars. stationplot.plot_parameter('NE', data['slp'], formatter=lambda v: format(10 * v, '.0f')[-3:]) # Plot the cloud cover symbols in the center location. This uses the codes made above and # uses the `sky_cover` mapper to convert these values to font codes for the # weather symbol font.
def plot_map_temperature(proj, point_locs, df_t, area='EU', west=-5.5, east=32, south=42, north=62, fonts=14, cm='gist_ncar', path=None, SLP=False): if path is None: # set up the paths and test for existence path = expanduser('~') + '/Documents/Metar_plots' try: os.listdir(path) except FileNotFoundError: os.mkdir(path) else: path = path df = df_t plt.rcParams['savefig.dpi'] = 300 # ========================================================================= # Create the figure and an axes set to the projection. fig = plt.figure(figsize=(20, 16)) ax = fig.add_subplot(1, 1, 1, projection=proj) if area == 'Antarctica': df = df.loc[df['latitude'] < north] ax.set_extent([-180, 180, -90, -60], ccrs.PlateCarree()) theta = np.linspace(0, 2 * np.pi, 100) center, radius = [0.5, 0.5], 0.5 verts = np.vstack([np.sin(theta), np.cos(theta)]).T circle = mpath.Path(verts * radius + center) ax.set_boundary(circle, transform=ax.transAxes) elif area == 'Arctic': df = df.loc[df['latitude'] > south] ax.set_extent([-180, 180, 60, 90], ccrs.PlateCarree()) theta = np.linspace(0, 2 * np.pi, 100) center, radius = [0.5, 0.5], 0.5 verts = np.vstack([np.sin(theta), np.cos(theta)]).T circle = mpath.Path(verts * radius + center) ax.set_boundary(circle, transform=ax.transAxes) else: ax.set_extent((west, east, south, north)) # Set up a cartopy feature for state borders. state_boundaries = feat.NaturalEarthFeature(category='cultural', name='admin_0_countries', scale='10m', facecolor='#d8dcd6', alpha=0.5) ax.coastlines(resolution='10m', zorder=1, color='black') ax.add_feature(state_boundaries, zorder=1, edgecolor='black') # ax.add_feature(cartopy.feature.OCEAN, zorder=0) # Set plot bounds # reset index for easier loop df = df.dropna(how='any', subset=['TT']) df = df.reset_index() cmap = matplotlib.cm.get_cmap(cm) norm = matplotlib.colors.Normalize(vmin=-30.0, vmax=30.0) # Start the station plot by specifying the axes to draw on, as well as the # lon/lat of the stations (with transform). We also the fontsize to 12 pt. index = 0 a = np.arange(-30, 30, 1) for x in a: if index == 0: df_min = df.loc[df['TT'] < min(a)] df_max = df.loc[df['TT'] > max(a)] j = 0 list_ex = [min(a) - 5, max(a) + 5] for arr in [df_min, df_max]: stationplot = StationPlot(ax, arr['longitude'], arr['latitude'], clip_on=True, transform=ccrs.PlateCarree(), fontsize=fonts) Temp = stationplot.plot_parameter('NW', arr['TT'], color=cmap(norm(list_ex[j]))) try: Temp.set_path_effects([ path_effects.Stroke(linewidth=1.5, foreground='black'), path_effects.Normal() ]) except AttributeError: pass j += 1 # slice out values between x and x+1 df_cur = df.loc[(df['TT'] < x + 1) & (df['TT'] >= x)] stationplot = StationPlot(ax, df_cur['longitude'], df_cur['latitude'], clip_on=True, transform=ccrs.PlateCarree(), fontsize=fonts) # plot the sliced values with a different color for each loop Temp = stationplot.plot_parameter('NW', df_cur['TT'], color=cmap(norm(x + 0.5))) try: Temp.set_path_effects([ path_effects.Stroke(linewidth=1.5, foreground='black'), path_effects.Normal() ]) except AttributeError: pass print('x={} done correctly '.format(x)) index += 1 # fontweight = 'bold' # More complex ex. uses custom formatter to control how sea-level pressure # values are plotted. This uses the standard trailing 3-digits of # the pressure value in tenths of millibars. stationplot = StationPlot(ax, df['longitude'].values, df['latitude'].values, clip_on=True, transform=ccrs.PlateCarree(), fontsize=fonts) try: u, v = wind_components(((df['ff'].values) * units('knots')), (df['dd'].values * units.degree)) cloud_frac = df['cloud_cover'] if area != 'Arctic': stationplot.plot_barb(u, v, zorder=1000, linewidth=2) stationplot.plot_symbol('C', cloud_frac, sky_cover) # stationplot.plot_text((2, 0), df['Station']) for val in range(0, 2): wx = df[['ww', 'StationType']] if val == 0: # mask all the unmanned stations wx['ww'].loc[wx['StationType'] > 3] = np.nan wx2 = wx['ww'].fillna(00).astype(int).values.tolist() stationplot.plot_symbol('W', wx2, current_weather, zorder=2000) else: # mask all the manned stations wx['ww'].loc[(wx['StationType'] <= 3)] = np.nan # mask all reports smaller than 9 # =7 is an empty symbol! wx['ww'].loc[wx['ww'] <= 9] = 7 wx2 = wx['ww'].fillna(7).astype(int).values.tolist() stationplot.plot_symbol('W', wx2, current_weather_auto, zorder=2000) # print(u, v) except (ValueError, TypeError) as error: pass if SLP is True: lon = df['longitude'].loc[(df.PressureDefId == 'mean sea level') & (df.Hp <= 750)].values lat = df['latitude'].loc[(df.PressureDefId == 'mean sea level') & (df.Hp <= 750)].values xp, yp, _ = proj.transform_points(ccrs.PlateCarree(), lon, lat).T sea_levelp = df['SLP'].loc[(df.PressureDefId == 'mean sea level') & (df.Hp <= 750)] x_masked, y_masked, pres = remove_nan_observations( xp, yp, sea_levelp.values) slpgridx, slpgridy, slp = interpolate_to_grid(x_masked, y_masked, pres, interp_type='cressman', search_radius=400000, rbf_func='quintic', minimum_neighbors=1, hres=100000, rbf_smooth=100000) Splot_main = ax.contour(slpgridx, slpgridy, slp, colors='k', linewidths=2, extent=(west, east, south, north), levels=list(range(950, 1050, 10))) plt.clabel(Splot_main, inline=1, fontsize=12, fmt='%i') Splot = ax.contour(slpgridx, slpgridy, slp, colors='k', linewidths=1, linestyles='--', extent=(west, east, south, north), levels=[ x for x in range(950, 1050, 1) if x not in list(range(950, 1050, 10)) ]) plt.clabel(Splot, inline=1, fontsize=10, fmt='%i') # stationplot.plot_text((2, 0), df['Station']) # Also plot the actual text of the station id. Instead of cardinal # directions, plot further out by specifying a location of 2 increments # in x and 0 in y.stationplot.plot_text((2, 0), df['station']) if (area == 'Antarctica' or area == 'Arctic'): plt.savefig(path + '/CURR_SYNOP_color_' + area + '.png', bbox_inches='tight', pad_inches=0) else: plt.savefig(path + '/CURR_SYNOP_color_' + area + '.png', bbox_inches='tight', transparent="True", pad_inches=0)
# Create the figure and an axes set to the projection. fig = plt.figure(figsize=(20, 8)) add_metpy_logo(fig, 70, 30, size='large') ax = fig.add_subplot(1, 1, 1, projection=proj) # Add some various map elements to the plot to make it recognizable. ax.add_feature(cfeature.LAND) ax.add_feature(cfeature.STATES.with_scale('50m')) # Set plot bounds ax.set_extent((-104, -93, 33.4, 37.2)) stationplot = StationPlot(ax, longitude.values, latitude.values, clip_on=True, transform=ccrs.PlateCarree(), fontsize=12) # Plot the temperature and dew point to the upper and lower left, respectively, of # the center point. Each one uses a different color. stationplot.plot_parameter('NW', temperature, color='red') stationplot.plot_parameter('SW', dewpoint, color='darkgreen') # A more complex example uses a custom formatter to control how the sea-level pressure # values are plotted. This uses the standard trailing 3-digits of the pressure value # in tenths of millibars. stationplot.plot_parameter('NE', pressure.m, formatter=lambda v: format(10 * v, '.0f')[-3:])