def define_grid(lon_0, lat_0, x_radius, y_radius, spacing, projected=False, plot_preview=False): """ Define the spatial grid of trial source locations. Grid can be defined in either a latitude/longitude or projected UTM (i.e., Cartesian) coordinate system. Args: lon_0: [deg] Longitude of grid center lat_0: [deg] Latitude of grid center x_radius: [deg or m] Distance from lon_0 to edge of grid (i.e., radius) y_radius: [deg or m] Distance from lat_0 to edge of grid (i.e., radius) spacing: [deg or m] Desired grid spacing projected: Boolean controlling whether a latitude/longitude or UTM grid is used. If True, a UTM grid is used and the units of x_radius, y_radius, and spacing are interpreted in meters instead of in degrees (default: False) plot_preview: Toggle plotting a preview of the grid for reference and troubleshooting (default: False) Returns: grid_out: xarray.DataArray object containing the grid coordinates and metadata """ print('-------------') print('DEFINING GRID') print('-------------') # Make coordinate vectors if projected: x_0, y_0, zone_number, _ = utm.from_latlon(lat_0, lon_0) else: x_0, y_0, = lon_0, lat_0 # Using np.linspace() in favor of np.arange() due to precision advantages x, dx = np.linspace(x_0 - x_radius, x_0 + x_radius, int(2 * x_radius / spacing) + 1, retstep=True) y, dy = np.linspace(y_0 - y_radius, y_0 + y_radius, int(2 * y_radius / spacing) + 1, retstep=True) # Basic grid checks if dx != spacing: warnings.warn( f'Requested spacing of {spacing} does not match ' f'np.linspace()-returned x-axis spacing of {dx}.', RTMWarning) if dy != spacing: warnings.warn( f'Requested spacing of {spacing} does not match ' f'np.linspace()-returned y-axis spacing of {dy}.', RTMWarning) if not (x_0 in x and y_0 in y): warnings.warn( '(x_0, y_0) is not located in grid. Check for numerical ' 'precision problems (i.e., rounding error).', RTMWarning) if projected: # Create list of grid corners corners = dict(SW=(x.min(), y.min()), NW=(x.min(), y.max()), NE=(x.max(), y.max()), SE=(x.max(), y.min())) for label, corner in corners.items(): # "Un-project" back to latitude/longitude lat, lon = utm.to_latlon(*corner, zone_number, northern=lat_0 >= 0, strict=False) # "Re-project" to UTM _, _, new_zone_number, _ = utm.from_latlon(lat, lon) if new_zone_number != zone_number: warnings.warn( f'{label} grid corner locates to UTM zone ' f'{new_zone_number} instead of origin UTM zone ' f'{zone_number}. Consider reducing grid extent ' 'or using an unprojected grid.', RTMWarning) # Create grid data = np.full((y.size, x.size), np.nan) # Initialize an array of NaNs # Add grid "metadata" attrs = dict(grid_center=(lon_0, lat_0), x_radius=x_radius, y_radius=y_radius, spacing=spacing) if projected: # Add the projection information to the grid metadata attrs['UTM'] = dict(zone=zone_number, southern_hemisphere=lat_0 < 0) else: attrs['UTM'] = None grid_out = DataArray(data, coords=[('y', y), ('x', x)], attrs=attrs) print('Done') # Plot grid preview, if specified if plot_preview: print('Generating grid preview plot...') if projected: proj = ccrs.UTM(**grid_out.UTM) transform = proj else: # This is a good projection to use since it preserves area proj = ccrs.AlbersEqualArea(central_longitude=lon_0, central_latitude=lat_0, standard_parallels=(y.min(), y.max())) transform = ccrs.PlateCarree() fig, ax = plt.subplots(figsize=(10, 10), subplot_kw=dict(projection=proj)) _plot_geographic_context(ax=ax, utm=projected) # Note that trial source locations are at the CENTER of each plotted # grid box grid_out.plot.pcolormesh(ax=ax, transform=transform, edgecolor='black', add_colorbar=False) # Plot the center of the grid ax.scatter(lon_0, lat_0, s=50, color='limegreen', edgecolor='black', label='Grid center', transform=ccrs.Geodetic()) # Add a legend ax.legend(loc='best') fig.canvas.draw() # Needed to make fig.tight_layout() work fig.tight_layout() fig.show() print('Done') return grid_out
from Visualization import * import cartopy.crs as ccrs import matplotlib.pyplot as plt #Figzise plt.figure(figsize=(10,5)) ax = plt.axes(projection=ccrs.PlateCarree()) ax.coastlines() #Central warehouses elc_lon, elc_lat = 10.33, 52.14 alc_lon, alc_lat = -87.63, 41.87 flc_lon, flc_lat = 114.1, 22.4 # Production facilities mx_lon, mx_lat = -117.04, 32.51 pl_lon, pl_lat = 21.01, 52.23 as_is_lon, as_is_lat = 114.06, 22.54 #Alternative to Geodetic = PlateCarree #MX plt.plot([mx_lon, elc_lon], [mx_lat, elc_lat], color='red', linewidth=2, alpha=0.5, marker='o', transform=ccrs.Geodetic(), ) plt.plot([mx_lon, flc_lon], [mx_lat, flc_lat], color='red', linewidth=2, alpha=0.5, marker='o', transform=ccrs.Geodetic(), )
import netCDF4 import numpy as np import cartopy.crs as ccrs from cartopy.mpl.gridliner import (LONGITUDE_FORMATTER, LATITUDE_FORMATTER) from typhon.plots.maps import get_cfeatures_at_scale # Read air temperature data. with netCDF4.Dataset('_data/test_data.nc') as nc: lon, lat = np.meshgrid(nc.variables['lon'][:], nc.variables['lat'][:]) temp = nc.variables['temp'][:] # Create plot with PlateCarree projection. fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection=ccrs.PlateCarree()) ax.set_extent([3, 16, 47, 56]) # Add map "features". features = get_cfeatures_at_scale(scale='50m') ax.add_feature(features.BORDERS) ax.add_feature(features.COASTLINE) ax.add_feature(features.LAND) ax.add_feature(features.OCEAN) # Plot the actual data. sm = ax.pcolormesh(lon, lat, temp, cmap='temperature', rasterized=True, transform=ccrs.PlateCarree(), )
ytick = [33.0, 33.5, 34, 34.5, 35, 35.5, 36.0, 36.5] axesrange = [134.4, 136.7, 33.75, 35.8] #Plot time mean of the moments. import matplotlib import matplotlib.pyplot as plt import matplotlib.ticker as mticker import cartopy.crs as ccrs blues = ['#001a33', '#004d99', '#0073e6', '#3399ff', '#66b3ff', '#b3d9ff'] reds = ['#ffb3b3', '#ff6666', '#ff0000', '#b30000', '#660000', '#1a0000'] fig = plt.figure(1, figsize=[6.5, 5]) ax = fig.add_subplot(111, projection=ccrs.PlateCarree()) #The pcolor smin = np.nanmin(my_data['topo']) smax = np.nanmax(my_data['topo']) p = ax.pcolor(lon, lat, topo, transform=ccrs.PlateCarree(), vmin=smin, vmax=smax, cmap=cpf.cmap_discretize('copper_r', 41)) ax.set_extent(axesrange, ccrs.PlateCarree()) topo[topo > 1.2] = np.nan
def feature(): unit_circle = sgeom.Point(0, 0).buffer(0.5) unit_square = unit_circle.envelope geoms = [unit_circle, unit_square] feature = ShapelyFeature(geoms, ccrs.PlateCarree()) return feature
def plot_em_global_tonnes(u_title, u_file_output, u_data, u_pl): # u_title = '' cbar_label = 'kg/' + 'km\u00b2' u_res_text = 'Resolution: 1 degree x 1 degree lat-lon' u_color = 'jet' #'YlOrBr' #'hot_r' #'jet' fig_w, fig_h = 12, 16 x_min, x_max, x_step = -180, 181, 60 y_min, y_max, y_step = -90, 91, 45 u_pl_min, u_pl_max = 10, 100000 fig, ax = plt.subplots(1, 1, figsize=(fig_w, fig_h), subplot_kw={"projection": ccrs.PlateCarree()}) u_data_pl = u_data[u_pl].fillna(u_pl_min) em = u_data_pl.plot.pcolormesh(ax=ax, norm=colors.LogNorm(vmin=u_pl_min, vmax=u_pl_max), cmap=u_color, add_colorbar=False, xticks=np.arange(x_min, x_max, step=x_step), yticks=np.arange(y_min, y_max, step=y_step)) cax = fig.add_axes([ ax.get_position().x1 + 0.01, ax.get_position().y0, 0.02, ax.get_position().height ]) cb = plt.colorbar(em, cax=cax, extend='both') cb.ax.set_title(cbar_label, fontsize=14, x=1.0, y=1.01) cb.ax.tick_params(labelsize=12) ax.set_title(u_title, fontweight='regular', fontsize=20) #'light','normal','regular','semibold','bold' ax.set_xlabel("") ax.set_ylabel("") lon_formatter = LongitudeFormatter() lat_formatter = LatitudeFormatter() ax.xaxis.set_major_formatter(lon_formatter) ax.yaxis.set_major_formatter(lat_formatter) ax.tick_params(axis='both', which='major', labelsize=12) ax.text(0.9, 0.025, u_res_text, horizontalalignment='right', verticalalignment='bottom', fontsize=12, color='white', transform=ax.transAxes) ax.coastlines(color='whitesmoke') #'dimgrey','white','whitesmoke' plt.savefig(u_file_output + '.svg', dpi=150, bbox_inches='tight', format='svg') plt.savefig(u_file_output + '.png', dpi=150, bbox_inches='tight', format='png') plt.savefig(u_file_output + '.pdf', dpi=150, bbox_inches='tight', format='pdf') plt.savefig(u_file_output + '.eps', dpi=150, bbox_inches='tight', format='eps') return
def main(): config = load_config() hazard_cols = ['hazard_type', 'climate_scenario', 'year'] duration = 10 hazard_set = [{ 'hazard': 'fluvial flooding', 'name': 'Fluvial flooding' }, { 'hazard': 'pluvial flooding', 'name': 'Pluvial flooding' }] change_colors = [ '#1a9850', '#66bd63', '#a6d96a', '#d9ef8b', '#fee08b', '#fdae61', '#f46d43', '#d73027', '#969696' ] change_labels = [ '< -100', '-100 to -50', '-50 to -10', '-10 to 0', '0 to 10', '10 to 50', '50 to 100', ' > 100', 'No change/value' ] change_ranges = [(-1e10, -100), (-100, -50), (-50, -10), (-10, 0), (0.001, 10), (10, 50), (50, 100), (100, 1e10)] eael_set = [{ 'column': 'min_eael', 'title': 'Min EAEL', 'legend_label': "EAEL (million USD)", 'divisor': 1000000, 'significance': 0 }, { 'column': 'max_eael', 'title': 'Max EAEL', 'legend_label': "EAEL (million USD)", 'divisor': 1000000, 'significance': 0 }] data_path = config['paths']['data'] region_file_path = os.path.join(config['paths']['data'], 'network', 'rail_edges.shp') flow_file_path = os.path.join(config['paths']['output'], 'flow_mapping_combined', 'weighted_flows_rail_100_percent.csv') region_file = gpd.read_file(region_file_path, encoding='utf-8') flow_file = pd.read_csv(flow_file_path) region_file = pd.merge(region_file, flow_file, how='left', on=['edge_id']).fillna(0) region_file = region_file[region_file['max_total_tons'] > 0] del flow_file flow_file_path = os.path.join( config['paths']['output'], 'failure_results', 'minmax_combined_scenarios', 'single_edge_failures_minmax_rail_100_percent_disrupt.csv') flow_file = pd.read_csv(flow_file_path) flow_file_path = os.path.join( config['paths']['output'], 'network_stats', 'rail_hazard_intersections_risk_weights.csv') fail_sc = pd.read_csv(flow_file_path) fail_scenarios = pd.merge(fail_sc, flow_file, how='left', on=['edge_id']).fillna(0) del flow_file, fail_sc fail_scenarios['min_eael'] = duration * fail_scenarios[ 'risk_wt'] * fail_scenarios['min_econ_impact'] fail_scenarios['max_eael'] = duration * fail_scenarios[ 'risk_wt'] * fail_scenarios['max_econ_impact'] all_edge_fail_scenarios = fail_scenarios[ hazard_cols + ['edge_id', 'min_eael', 'max_eael']] all_edge_fail_scenarios = all_edge_fail_scenarios.groupby( hazard_cols + ['edge_id'])['min_eael', 'max_eael'].max().reset_index() # Climate change effects all_edge_fail_scenarios = all_edge_fail_scenarios.set_index( ['hazard_type', 'edge_id']) scenarios = list(set(all_edge_fail_scenarios.index.values.tolist())) change_tup = [] for sc in scenarios: eael = all_edge_fail_scenarios.loc[[sc], 'max_eael'].values.tolist() yrs = all_edge_fail_scenarios.loc[[sc], 'year'].values.tolist() cl = all_edge_fail_scenarios.loc[[sc], 'climate_scenario'].values.tolist() if 2016 not in yrs: for e in range(len(eael)): if eael[e] > 0: # change_tup += list(zip([sc[0]]*len(cl),[sc[1]]*len(cl),cl,yrs,[0]*len(cl),eael,[1e9]*len(cl))) change_tup += [(sc[0], sc[1], cl[e], yrs[e], 0, eael[e], 1e9)] elif len(yrs) > 1: vals = list(zip(cl, eael, yrs)) vals = sorted(vals, key=lambda pair: pair[-1]) change = 100.0 * (np.array([p for (c, p, y) in vals[1:]]) - vals[0][1]) / vals[0][1] cl = [c for (c, p, y) in vals[1:]] yrs = [y for (c, p, y) in vals[1:]] fut = [p for (c, p, y) in vals[1:]] change_tup += list( zip([sc[0]] * len(cl), [sc[1]] * len(cl), cl, yrs, [vals[0][1]] * len(cl), fut, change)) change_df = pd.DataFrame(change_tup, columns=[ 'hazard_type', 'edge_id', 'climate_scenario', 'year', 'current', 'future', 'change' ]).fillna('inf') change_df = change_df[change_df['change'] != 'inf'] change_df.to_csv(os.path.join(config['paths']['output'], 'network_stats', 'national_rail_eael_climate_change.csv'), index=False) # Change effects change_df = change_df.set_index(hazard_cols) scenarios = list(set(change_df.index.values.tolist())) for sc in scenarios: hazard_type = sc[0] climate_scenario = sc[1] year = sc[2] percentage = change_df.loc[[sc], 'change'].values.tolist() edges = change_df.loc[[sc], 'edge_id'].values.tolist() edges_df = pd.DataFrame(list(zip(edges, percentage)), columns=['edge_id', 'change']) edges_vals = pd.merge(region_file, edges_df, how='left', on=['edge_id']).fillna(0) del percentage, edges, edges_df proj_lat_lon = ccrs.PlateCarree() ax = get_axes() plot_basemap(ax, data_path) scale_bar(ax, location=(0.8, 0.05)) plot_basemap_labels(ax, data_path, include_regions=True) name = [c['name'] for c in hazard_set if c['hazard'] == hazard_type][0] for record in edges_vals.itertuples(): geom = record.geometry region_val = record.change if region_val: cl = [ c for c in range(len((change_ranges))) if region_val >= change_ranges[c][0] and region_val < change_ranges[c][1] ] if cl: c = cl[0] ax.add_geometries([geom], crs=proj_lat_lon, linewidth=2.0, edgecolor=change_colors[c], facecolor='none', zorder=8) # ax.add_geometries([geom.buffer(0.1)],crs=proj_lat_lon,linewidth=0,facecolor=change_colors[c],edgecolor='none',zorder=8) else: ax.add_geometries([geom], crs=proj_lat_lon, linewidth=1.5, edgecolor=change_colors[-1], facecolor='none', zorder=7) # ax.add_geometries([geom.buffer(0.1)], crs=proj_lat_lon, linewidth=0,facecolor=change_colors[-1],edgecolor='none',zorder=7) # Legend legend_handles = [] for c in range(len(change_colors)): legend_handles.append( mpatches.Patch(color=change_colors[c], label=change_labels[c])) ax.legend(handles=legend_handles, title='Percentage change in EAEL', loc=(0.55, 0.2), fancybox=True, framealpha=1.0) if climate_scenario == 'none': climate_scenario = 'current' else: climate_scenario = climate_scenario.upper() title = 'Percentage change in EAEL for {} {} {}'.format( name, climate_scenario.replace('_', ' ').title(), year) print(" * Plotting {}".format(title)) plt.title(title, fontsize=10) output_file = os.path.join( config['paths']['figures'], 'national-rail-{}-{}-{}-risks-change-percentage.png'.format( name, climate_scenario.replace('-', ' ').title(), year)) save_fig(output_file) plt.close() # Absolute effects all_edge_fail_scenarios = all_edge_fail_scenarios.reset_index() all_edge_fail_scenarios = all_edge_fail_scenarios.set_index(hazard_cols) scenarios = list(set(all_edge_fail_scenarios.index.values.tolist())) for sc in scenarios: hazard_type = sc[0] climate_scenario = sc[1] if climate_scenario == 'none': climate_scenario = 'current' else: climate_scenario = climate_scenario.upper() year = sc[2] min_eael = all_edge_fail_scenarios.loc[[sc], 'min_eael'].values.tolist() max_eael = all_edge_fail_scenarios.loc[[sc], 'max_eael'].values.tolist() edges = all_edge_fail_scenarios.loc[[sc], 'edge_id'].values.tolist() edges_df = pd.DataFrame(list(zip(edges, min_eael, max_eael)), columns=['edge_id', 'min_eael', 'max_eael']) edges_vals = pd.merge(region_file, edges_df, how='left', on=['edge_id']).fillna(0) del edges_df for c in range(len(eael_set)): proj_lat_lon = ccrs.PlateCarree() ax = get_axes() plot_basemap(ax, data_path) scale_bar(ax, location=(0.8, 0.05)) plot_basemap_labels(ax, data_path, include_regions=True) # generate weight bins column = eael_set[c]['column'] weights = [ record[column] for iter_, record in edges_vals.iterrows() ] max_weight = max(weights) width_by_range = generate_weight_bins(weights, width_step=0.04, n_steps=5) rail_geoms_by_category = {'1': [], '2': []} for iter_, record in edges_vals.iterrows(): geom = record.geometry val = record[column] if val == 0: cat = '2' else: cat = '1' buffered_geom = None for (nmin, nmax), width in width_by_range.items(): if nmin <= val and val < nmax: buffered_geom = geom.buffer(width) if buffered_geom is not None: rail_geoms_by_category[cat].append(buffered_geom) else: print("Feature was outside range to plot", iter_) styles = OrderedDict([ ('1', Style(color='#006d2c', zindex=9, label='Hazard failure effect')), # green ('2', Style(color='#969696', zindex=7, label='No hazard exposure/effect')) ]) for cat, geoms in rail_geoms_by_category.items(): cat_style = styles[cat] ax.add_geometries(geoms, crs=proj_lat_lon, linewidth=0, facecolor=cat_style.color, edgecolor='none', zorder=cat_style.zindex) name = [ h['name'] for h in hazard_set if h['hazard'] == hazard_type ][0] x_l = -62.4 x_r = x_l + 0.4 base_y = -42.1 y_step = 0.8 y_text_nudge = 0.2 x_text_nudge = 0.2 ax.text(x_l, base_y + y_step - y_text_nudge, eael_set[c]['legend_label'], horizontalalignment='left', transform=proj_lat_lon, size=10) divisor = eael_set[c]['divisor'] significance_ndigits = eael_set[c]['significance'] max_sig = [] for (i, ((nmin, nmax), line_style)) in enumerate(width_by_range.items()): if round(nmin / divisor, significance_ndigits) < round( nmax / divisor, significance_ndigits): max_sig.append(significance_ndigits) elif round(nmin / divisor, significance_ndigits + 1) < round( nmax / divisor, significance_ndigits + 1): max_sig.append(significance_ndigits + 1) elif round(nmin / divisor, significance_ndigits + 2) < round( nmax / divisor, significance_ndigits + 2): max_sig.append(significance_ndigits + 2) else: max_sig.append(significance_ndigits + 3) significance_ndigits = max(max_sig) for (i, ((nmin, nmax), width)) in enumerate(width_by_range.items()): y = base_y - (i * y_step) line = LineString([(x_l, y), (x_r, y)]).buffer(width) ax.add_geometries([line], crs=proj_lat_lon, linewidth=0, edgecolor='#000000', facecolor='#000000', zorder=2) if nmin == max_weight: value_template = '>{:.' + str(significance_ndigits) + 'f}' label = value_template.format( round(max_weight / divisor, significance_ndigits)) else: value_template = '{:.' + str(significance_ndigits) + \ 'f}-{:.' + str(significance_ndigits) + 'f}' label = value_template.format( round(nmin / divisor, significance_ndigits), round(nmax / divisor, significance_ndigits)) ax.text(x_r + x_text_nudge, y - y_text_nudge, label, horizontalalignment='left', transform=proj_lat_lon, size=10) if climate_scenario == 'none': climate_scenario = 'Current' climate_scenario = climate_scenario.replace('_', ' ') title = 'Railways ({}) {} {} {}'.format(eael_set[c]['title'], name, climate_scenario.title(), year) print('* Plotting ', title) plt.title(title, fontsize=12) legend_from_style_spec(ax, styles, loc='lower left') # output output_file = os.path.join( config['paths']['figures'], 'national-rail-{}-{}-{}-{}.png'.format( name.replace(' ', ''), climate_scenario.replace('.', ''), year, eael_set[c]['column'])) save_fig(output_file) plt.close()
def project_extents(extents, src_proj, dest_proj, tol=1e-6): x1, y1, x2, y2 = extents if (isinstance(src_proj, ccrs.PlateCarree) and not isinstance(dest_proj, ccrs.PlateCarree) and src_proj.proj4_params['lon_0'] != 0): xoffset = src_proj.proj4_params['lon_0'] x1 = x1 - xoffset x2 = x2 - xoffset src_proj = ccrs.PlateCarree() # Limit latitudes cy1, cy2 = src_proj.y_limits if y1 < cy1: y1 = cy1 if y2 > cy2: y2 = cy2 # Offset with tolerances x1 += tol x2 -= tol y1 += tol y2 -= tol # Wrap longitudes cx1, cx2 = src_proj.x_limits if isinstance(src_proj, ccrs._CylindricalProjection): lons = wrap_lons(np.linspace(x1, x2, 10000), -180., 360.) x1, x2 = lons.min(), lons.max() else: if x1 < cx1: x1 = cx1 if x2 > cx2: x2 = cx2 domain_in_src_proj = Polygon([[x1, y1], [x2, y1], [x2, y2], [x1, y2], [x1, y1]]) boundary_poly = Polygon(src_proj.boundary) dest_poly = src_proj.project_geometry(Polygon(dest_proj.boundary), dest_proj).buffer(0) if src_proj != dest_proj: # Erode boundary by threshold to avoid transform issues. # This is a workaround for numerical issues at the boundary. eroded_boundary = boundary_poly.buffer(-src_proj.threshold) geom_in_src_proj = eroded_boundary.intersection( domain_in_src_proj) try: geom_clipped_to_dest_proj = dest_poly.intersection( geom_in_src_proj) except: geom_clipped_to_dest_proj = None if geom_clipped_to_dest_proj: geom_in_src_proj = geom_clipped_to_dest_proj try: geom_in_crs = dest_proj.project_geometry(geom_in_src_proj, src_proj) except ValueError: src_name =type(src_proj).__name__ dest_name =type(dest_proj).__name__ raise ValueError('Could not project data from %s projection ' 'to %s projection. Ensure the coordinate ' 'reference system (crs) matches your data ' 'and the kdims.' % (src_name, dest_name)) else: geom_in_crs = boundary_poly.intersection(domain_in_src_proj) return geom_in_crs.bounds
def plot_map(ds: xr.Dataset, var: VarName.TYPE = None, index: DictLike.TYPE = None, time: Union[str, int] = None, region: PolygonLike.TYPE = None, projection: str = 'PlateCarree', central_lon: float = 0.0, file: str = None) -> None: """ Plot the given variable from the given dataset on a map with coastal lines. In case no variable name is given, the first encountered variable in the dataset is plotted. In case no time index is given, the first time slice is taken. It is also possible to set extents of the plot. If no extents are given, a global plot is created. The plot can either be shown using pyplot functionality, or saved, if a path is given. The following file formats for saving the plot are supported: eps, jpeg, jpg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff :param ds: xr.Dataset to plot :param var: variable name in the dataset to plot :param index: Optional index into the variable's data array. The *index* is a dictionary that maps the variable's dimension names to constant labels. For example, ``lat`` and ``lon`` are given in decimal degrees, while a ``time`` value may be provided as datetime object or a date string. *index* may also be a comma-separated string of key-value pairs, e.g. "lat=12.4, time='2012-05-02'". :param time: time slice index to plot :param region: Region to plot :param projection: name of a global projection, see http://scitools.org.uk/cartopy/docs/v0.15/crs/projections.html :param central_lon: central longitude of the projection in degrees :param file: path to a file in which to save the plot """ if not isinstance(ds, xr.Dataset): raise NotImplementedError('Only raster datasets are currently ' 'supported') var_name = None if not var: for key in ds.data_vars.keys(): var_name = key break else: var_name = VarName.convert(var) var = ds[var_name] index = DictLike.convert(index) # 0 is a valid index, hence test if time is None if time is not None and isinstance(time, int) and 'time' in var.coords: time = var.coords['time'][time] if time: if not index: index = dict() index['time'] = time for dim_name in var.dims: if dim_name not in ('lat', 'lon'): if not index: index = dict() if dim_name not in index: index[dim_name] = 0 if region is None: lat_min = -90.0 lat_max = 90.0 lon_min = -180.0 lon_max = 180.0 else: region = PolygonLike.convert(region) lon_min, lat_min, lon_max, lat_max = region.bounds if not _check_bounding_box(lat_min, lat_max, lon_min, lon_max): raise ValueError( 'Provided plot extents do not form a valid bounding box ' 'within [-180.0,+180.0,-90.0,+90.0]') extents = [lon_min, lon_max, lat_min, lat_max] # See http://scitools.org.uk/cartopy/docs/v0.15/crs/projections.html# if projection == 'PlateCarree': proj = ccrs.PlateCarree(central_longitude=central_lon) elif projection == 'LambertCylindrical': proj = ccrs.LambertCylindrical(central_longitude=central_lon) elif projection == 'Mercator': proj = ccrs.Mercator(central_longitude=central_lon) elif projection == 'Miller': proj = ccrs.Miller(central_longitude=central_lon) elif projection == 'Mollweide': proj = ccrs.Mollweide(central_longitude=central_lon) elif projection == 'Orthographic': proj = ccrs.Orthographic(central_longitude=central_lon) elif projection == 'Robinson': proj = ccrs.Robinson(central_longitude=central_lon) elif projection == 'Sinusoidal': proj = ccrs.Sinusoidal(central_longitude=central_lon) elif projection == 'NorthPolarStereo': proj = ccrs.NorthPolarStereo(central_longitude=central_lon) elif projection == 'SouthPolarStereo': proj = ccrs.SouthPolarStereo(central_longitude=central_lon) else: raise ValueError('illegal projection') try: if index: var_data = var.sel(**index) else: var_data = var except ValueError: var_data = var fig = plt.figure(figsize=(16, 8)) ax = plt.axes(projection=proj) if extents: ax.set_extent(extents) else: ax.set_global() ax.coastlines() var_data.plot.contourf(ax=ax, transform=proj) if file: fig.savefig(file)
nlayers = 20 MAP_COLOR_LIMS = {'ec550dryaer': [0, 1000]} if var in MAP_COLOR_LIMS: map_vmin, map_vmax = MAP_COLOR_LIMS[var] else: map_vmin, map_vmax = vardef.map_vmin, vardef.map_vmax if any([x is None for x in [map_vmin, map_vmax]]): raise ValueError cm = plt.cm.get_cmap('Reds', nlayers) levels = np.linspace(map_vmin, map_vmax, nlayers) proj = ccrs.PlateCarree() ax = plt.axes(projection=proj) csf = {} if not data.check_dimcoords_tseries(): data.reorder_dimensions_tseries() nparr = data.cube.data lats = data.latitude.points lons = data.longitude.points geojson = {} for i, month in enumerate(data.time_stamps()): date = str(month).split('T')[0]
def plot_panel(n, fig, proj, pole, var, clevels, cmap, title, parameters, stats=None): var = add_cyclic(var) lon = var.getLongitude() lat = var.getLatitude() var = ma.squeeze(var.asma()) # Contour levels levels = None norm = None if len(clevels) > 0: levels = [-1.0e8] + clevels + [1.0e8] norm = colors.BoundaryNorm(boundaries=levels, ncolors=256) # Contour plot ax = fig.add_axes(panel[n], projection=proj) ax.set_global() ax.gridlines() if pole == 'N': ax.set_extent([-180, 180, 50, 90], crs=ccrs.PlateCarree()) elif pole == 'S': ax.set_extent([-180, 180, -55, -90], crs=ccrs.PlateCarree()) cmap = get_colormap(cmap, parameters) p1 = ax.contourf( lon, lat, var, transform=ccrs.PlateCarree(), norm=norm, levels=levels, cmap=cmap, extend='both', ) ax.set_aspect('auto') ax.coastlines(lw=0.3) 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) # Plot titles for i in range(3): if title[i] == None: title[i] = '' t = ax.set_title('%s\n%s' % (title[0], title[2]), loc='left', fontdict=plotSideTitle) t = ax.set_title(title[1], fontdict=plotTitle) if title[0] != '' or title[2] != '': t.set_position([.5, 1.06]) # Color bar cbax = fig.add_axes( (panel[n][0] + 0.35, panel[n][1] + 0.0354, 0.0326, 0.1792)) cbar = fig.colorbar(p1, cax=cbax) w, h = get_ax_size(fig, cbax) if levels == None: cbar.ax.tick_params(labelsize=9.0, length=0) else: maxval = np.amax(np.absolute(levels[1:-1])) if maxval < 10.0: fmt = "%5.2f" pad = 25 elif maxval < 100.0: fmt = "%5.1f" pad = 25 else: fmt = "%6.1f" pad = 30 cbar.set_ticks(levels[1:-1]) labels = [fmt % l for l in levels[1:-1]] cbar.ax.set_yticklabels(labels, ha='right') cbar.ax.tick_params(labelsize=9.0, pad=pad, length=0) # Min, Mean, Max fig.text(panel[n][0] + 0.35, panel[n][1] + 0.225, "Max\nMean\nMin", ha='left', fontdict=plotSideTitle) fig.text(panel[n][0] + 0.45, panel[n][1] + 0.225, "%.2f\n%.2f\n%.2f" % stats[0:3], ha='right', fontdict=plotSideTitle) # RMSE, CORR if len(stats) == 5: fig.text(panel[n][0] + 0.35, panel[n][1] + 0., "RMSE\nCORR", ha='left', fontdict=plotSideTitle) fig.text(panel[n][0] + 0.45, panel[n][1] + 0., "%.2f\n%.2f" % stats[3:5], ha='right', fontdict=plotSideTitle)
''' This dataset is for rainfall satellite estimations from the PERSIANN platform only for the Amazon Basin area. You can easily select the area and download the data at the Portal: https://chrsdata.eng.uci.edu/ The shapefile for the Basin comes with the data. ''' dset = xr.open_dataset('CDR_amazonbasin.nc') # masking undefined values outside the basin area dset['precip'] = dset['precip'].where(dset['precip'] != -99.) # seasonal cycle season = dset['precip'].groupby('datetime.season').mean('datetime') basin = 'amazon_shape.shp' # shapefile proj = ccrs.PlateCarree() # cartopy projection f, ax = plot.subplots(axwidth=3.5, nrows=2, ncols=2, tight=True, proj='pcarree', proj_kw={'lon_0':180},) ax.format(land=False, coast=True, innerborders=True, borders=True, grid=False, geogridlinewidth=0, labels=True, latlim=(-21, 12), lonlim=(275, 315), latlines=plot.arange(-20, 10, 5), lonlines=plot.arange(-95, -20, 5), large='15px') map1 = ax[0,0].contourf(dset['lon'], dset['lat'], season[0,:,:], cmap='BuPu', levels=np.arange(50, 500, 50), extend='both') map2 = ax[0,1].contourf(dset['lon'], dset['lat'], season[2,:,:], cmap='BuPu', levels=np.arange(50, 500, 50), extend='both') map3 = ax[1,0].contourf(dset['lon'], dset['lat'], season[1,:,:],
Months[:] = np.NaN for i in np.arange(len(Months)): #Months[i]=int(str(AllData.iloc[i,2])[5:7]) Months[i] = int(str(O2invData.iloc[i, 3])[5:7]) O2invData['Month'] = Months lon = O2invData.loc[:, 'Lon'] lat = O2invData.loc[:, 'Lat'] O2inv = O2invData.loc[:, 'O2Inv'] O2eqinv = O2invData.loc[:, 'O2EqInv'] DiffInv = O2inv - O2eqinv O2invData['DiffEq'] = DiffInv fig, axs = plt.subplots(1, 1, figsize=(10, 6)) ax = plt.subplot(1, 1, 1, projection=ccrs.PlateCarree()) ax.coastlines('50m') ax.set_extent([lab_W, lab_E, lab_S, lab_N], ccrs.PlateCarree()) cm_cbr = ax.scatter(lon, lat, c=O2inv, vmin=minval, vmax=maxval, marker='o', s=2, cmap=cmap_choice) #cmo.balance ax.set_title('Total Oxygen Inventory (mol/m2)') fig.colorbar(cm_cbr) plt.savefig(FigDir + 'Map_Inventory_Total.jpg') plt.close()
except ImportError: WebMapService = None WebFeatureService = None _OWSLIB_AVAILABLE = False import cartopy.crs as ccrs from cartopy.io import LocatedImage, RasterSource from cartopy.img_transform import warp_array _OWSLIB_REQUIRED = 'OWSLib is required to use OGC web services.' # Hardcode some known EPSG codes for now. # The order given here determines the preferred SRS for WMS retrievals. _CRS_TO_OGC_SRS = collections.OrderedDict( [(ccrs.PlateCarree(), 'EPSG:4326'), (ccrs.GOOGLE_MERCATOR, 'EPSG:900913')]) # Standard pixel size of 0.28 mm as defined by WMTS. METERS_PER_PIXEL = 0.28e-3 _WGS84_METERS_PER_UNIT = 2 * math.pi * 6378137 / 360 METERS_PER_UNIT = { 'urn:ogc:def:crs:EPSG::27700': 1, 'urn:ogc:def:crs:EPSG::900913': 1, 'urn:ogc:def:crs:OGC:1.3:CRS84': _WGS84_METERS_PER_UNIT, } _URN_TO_CRS = { 'urn:ogc:def:crs:EPSG::27700': ccrs.OSGB(),
def plot_data(pwrf, pgrid, gridded_data, lon_pts, lat_pts): """plot_data: Plot the data Input: pwrf -- (class) ModelData pgrid -- class AnalysisGrid gridded_data -- (masked-array) frontal strength values lon_pts -- (list) Longitude points of front lat_pts -- (list) Latitude points of front Output: Optional: Save Figure None """ ## Get/Store WPS Data - recreate the domain wps = wps_info(pwrf.wpsfile) ## SET UP PLOT fig1 = plt.figure(figsize=[8, 8], dpi=100) ax1 = plt.axes(projection=wps.calc_wps_domain_info()[0]) #wpsproj - namelist.wps ax1.set_title("WRFv4 "+ pwrf.version +" Frontal Strength\nTime: "+\ pwrf.wrf_dt[pwrf.time_idx].strftime("%Y-%m-%d %H:%M")+"Z",\ size=20) #Plot the front threshold data (after it's been cleaned) plt1 = plt.pcolormesh(pwrf.lons[pgrid.south_start:pgrid.north_end,\ pgrid.west_start:pgrid.east_end-pgrid.gradient_distance],\ pwrf.lats[pgrid.south_start:pgrid.north_end,\ pgrid.west_start:pgrid.east_end-pgrid.gradient_distance],\ gridded_data[pgrid.south_start:pgrid.north_end,\ pgrid.west_start:pgrid.east_end-pgrid.gradient_distance],\ cmap='jet', vmin=pgrid.threshold, vmax=3, transform=ccrs.PlateCarree()) plt1.cmap.set_under("white") #plot the front points for ijk in range(len(lon_pts)): ax1.plot(lon_pts[ijk], lat_pts[ijk], 'rp', markersize=4, transform=ccrs.PlateCarree()) #Add map layers for counties/states/coastlines/etc. try: reader = shpreader.Reader(os.getcwd()+'/countyl010g_shp_nt00964/countyl010g.shp') counties = list(reader.geometries()) obj_counties = cfeature.ShapelyFeature(counties, ccrs.PlateCarree()) ax1.add_feature(obj_counties, facecolor='none', edgecolor='darkslategray') except ImportError: ax1.add_feature(cartopy.feature.STATES.with_scale('10m'),\ edgecolor='darkslategray', linewidth=1) ax1.coastlines('10m', 'darkslategray', linewidth=1) # Set/Add colorbar cbar_ax = fig1.add_axes([0, 0, 0.1, 0.1]) posn = ax1.get_position() cbar_ax.set_position([posn.x0 + posn.width + 0.01, posn.y0, 0.04, posn.height]) plt.colorbar(plt1, cax=cbar_ax, extend='min') if pwrf.save: plt.savefig(pwrf.mappath+"/Frontal_Strength_Analysis_"+\ pwrf.wrf_dt[pwrf.time_idx].strftime("%Y_%m_%d_%H%M")+\ "_"+pwrf.version+".png", transparent=True, dpi=600) else: plt.show() plt.close()
def plot_diff(slice1, title, lim1, lim2, step): #plt.figure() plt.figure(figsize=(12, 6)) # this works #plt.figure(figsize=(12, 4.8))# this works data = slice1.data lon = slice1.coord('longitude').points lat = slice1.coord('latitude').points new_lon = [] for k in range(len(lon)): if lon[k] > 180: #temp=lon[k] temp = lon[k] - 360 new_lon = np.append(new_lon, temp) else: new_lon = np.append(new_lon, lon[k]) #lon=lon-180 #basemap correction #new_lon=temp #..............basemap requires lat and lon to be in increasing order data_1 = data[:, 0:96] data_2 = data[:, 96:] data_21 = np.hstack((data_2, data_1)) new_lon_1 = new_lon[0:96] new_lon_2 = new_lon[96:] new_lon_21 = np.hstack((new_lon_2, new_lon_1)) data_final = data_21 new_lon_final = new_lon_21 ticks = np.arange(lim1, lim2, step) ticks6 = [1e0, 1e3, 1e5, 1e8, 1e10] ticks6_label = ['1e0', '1e3', '1e5', '1e8', '1e10'] ticks6 = [1e-2, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9] ticks6_label = [ '-1e2', '1e0', '1e1', '1e2', '1e3', '1e4', '1e5', '1e6', '1e7', '1e8', '1e9' ] ticks6 = [1e-33, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9] ticks6_label = [ '-1e2', '1e0', '1e1', '1e2', '1e3', '1e4', '1e5', '1e6', '1e7', '1e8', '1e9' ] ticks6 = [1e-35, 1e-30, 1e-25, 1e-20, 1e-15] ticks6_label = ['1e-35', '1e-30', '1e-25', '1e-20', '1e-15'] ticks6 = [1e-35, 1e-32, 1e-29, 1e-26, 1e-23, 1e-20, 1e-17, 1e-14] ticks6_label = [ '1e-35', '1e-32', '1e-29', '1e-26', '1e-23', '1e-20', '1e-17', '1e-14' ] ticks6 = [1e-20, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0] ticks6 = [1e-20, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0] ticks6 = [-300, -250, -200, -150, -100, -50, 0, 50] # this is a percentage change plot ticks6 = [-100, -90, -80, -70, -60, -50, -40, -30, -20, -10, 0] # this is a percentage change plot ticks6_label = [str(o) for o in ticks6] #ticks6_label = ['1e-35','1e-32','1e-29','1e-26','1e-23','1e-20','1e-17','1e-14'] #ticks6_label = ['1e-35','1e-30','1e-25','1e-20','1e-15'] #ticks6_label = ['-1e2','1e0','1e1','1e2','1e3','1e4','1e5','1e6','1e7','1e8','1e9'] # ticks6 = [-1e-22,1e-30,1e-16] # ticks6_label = ['-1e-22','1e-30','1e-16'] ax = plt.axes(projection=ccrs.PlateCarree()) #data_final = np.where(data_final>1.0,data_final,1e-1) #x=plt.contourf(new_lon_final,lat,data_final,transform=ccrs.PlateCarree(),cmap='RdYlBu_r',levels=ticks) #x=plt.contourf(new_lon_final,lat,data_final,norm=colors.LogNorm(vmin=1e-8,vmax=1e0),transform=ccrs.PlateCarree(),cmap='RdYlBu_r',levels=ticks6) x = plt.contourf(new_lon_final, lat, data_final, vmin=-100, vmax=0, transform=ccrs.PlateCarree(), cmap='RdGy', levels=ticks6) #x=plt.contourf(new_lon_final,lat,data_final,norm=colors.LogNorm(vmin=pow(10,-35),vmax=1e-15),transform=ccrs.PlateCarree(),cmap='RdYlBu_r',levels=ticks6) norm = mpl.colors.Normalize(vmin=lim1, vmax=lim2) #plt.title(title,fontdict={'fontsize':16}) plt.title(title, fontsize=12) ax.coastlines() gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=2, color='black', alpha=0.5, linestyle='--') gl.xlabels_top = False gl.ylabels_right = False #gl.xlines = False gl.xlocator = mticker.FixedLocator([-180, -90, 0, 90, 180]) gl.ylocator = mticker.FixedLocator([-90, -45, 0, 45, 90]) gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER gl.xlabel_style = {'size': 15, 'color': 'gray'} gl.xlabel_style = {'color': 'black', 'weight': 'bold'} gl.ylabel_style = {'size': 15, 'color': 'gray'} gl.ylabel_style = {'color': 'black', 'weight': 'bold'} """ cbar=plt.colorbar(x,ax=ax,ticks=ticks) cbar.ax.tick_params(labelsize=16) ax.set_aspect('auto') plt.savefig(title+'.png') """ cbar = plt.colorbar(x, ax=ax) cbar.set_ticks(ticks6) cbar.set_ticklabels(ticks6_label) cbar.ax.tick_params(labelsize=16) ax.set_aspect('auto')
_OWSLIB_AVAILABLE = True except ImportError: WebMapService = None WebFeatureService = None _OWSLIB_AVAILABLE = False import cartopy.crs as ccrs from cartopy.io import LocatedImage, RasterSource from cartopy.img_transform import warp_array _OWSLIB_REQUIRED = 'OWSLib is required to use OGC web services.' # Hardcode some known EPSG codes for now. # The order given here determines the preferred SRS for WMS retrievals. _CRS_TO_OGC_SRS = collections.OrderedDict([ (ccrs.PlateCarree(), 'EPSG:4326'), (ccrs.Mercator.GOOGLE, 'EPSG:900913'), (ccrs.OSGB(approx=True), 'EPSG:27700') ]) # Standard pixel size of 0.28 mm as defined by WMTS. METERS_PER_PIXEL = 0.28e-3 _WGS84_METERS_PER_UNIT = 2 * math.pi * 6378137 / 360 METERS_PER_UNIT = { 'urn:ogc:def:crs:EPSG::27700': 1, 'urn:ogc:def:crs:EPSG::900913': 1, 'urn:ogc:def:crs:OGC:1.3:CRS84': _WGS84_METERS_PER_UNIT, 'urn:ogc:def:crs:EPSG::3031': 1, 'urn:ogc:def:crs:EPSG::3413': 1, 'urn:ogc:def:crs:EPSG::3857': 1,
region=region, spacing=spacing) grid = chain.grid( region=region, spacing=spacing, projection=projection, dims=["latitude", "longitude"], data_names=["velocity"], ) grid = grid.where(mask) fig, axes = plt.subplots(1, 2, figsize=(9, 7), subplot_kw=dict(projection=ccrs.Mercator())) crs = ccrs.PlateCarree() # Plot the data uncertainties ax = axes[0] ax.set_title("Data uncertainty") # Plot the uncertainties in mm/yr and using a power law for the color scale to highlight # the smaller values pc = ax.scatter(*coordinates, c=data.std_up * 1000, s=20, cmap="magma", transform=crs, norm=PowerNorm(gamma=1 / 2)) cb = plt.colorbar(pc, ax=ax, orientation="horizontal", pad=0.05) cb.set_label("uncertainty [mm/yr]") vd.datasets.setup_california_gps_map(ax) # Plot the gridded velocities
def main(): config = load_config() data_path = config['paths']['data'] mode_file_path = os.path.join(config['paths']['data'], 'network', 'road_edges.shp') flow_file_path = os.path.join(config['paths']['output'], 'flow_mapping_combined', 'weighted_flows_road_100_percent.csv') mode_file = gpd.read_file(mode_file_path, encoding='utf-8') flow_file = pd.read_csv(flow_file_path) mode_file = pd.merge(mode_file, flow_file, how='left', on=['edge_id']).fillna(0) mode_file = mode_file[(mode_file['road_type'] == 'national') | (mode_file['road_type'] == 'province') | (mode_file['road_type'] == 'rural')] plot_sets = [ { 'file_tag': 'tmda', 'legend_label': "AADT ('000 vehicles/day)", 'divisor': 1000, 'columns': ['tmda_count'], 'title_cols': ['Vehicle Count'], 'significance': 0 }, { 'file_tag': 'commodities', 'legend_label': "AADF ('000 tons/day)", 'divisor': 1000, 'columns': [ 'max_{}'.format(x) for x in [ 'total_tons', 'AGRICULTURA, GANADERÍA, CAZA Y SILVICULTURA', 'Carnes', 'Combustibles', 'EXPLOTACIÓN DE MINAS Y CANTERAS', 'Granos', 'INDUSTRIA MANUFACTURERA', 'Industrializados', 'Mineria', 'PESCA', 'Regionales', 'Semiterminados' ] ], 'title_cols': [ 'Total tonnage', 'AGRICULTURA, GANADERÍA, CAZA Y SILVICULTURA', 'Carnes', 'Combustibles', 'EXPLOTACIÓN DE MINAS Y CANTERAS', 'Granos', 'INDUSTRIA MANUFACTURERA', 'Industrializados', 'Mineria', 'PESCA', 'Regionales', 'Semiterminados' ], 'significance': 0 }, ] for plot_set in plot_sets: for c in range(len(plot_set['columns'])): # basemap proj_lat_lon = ccrs.PlateCarree() ax = get_axes() plot_basemap(ax, data_path) scale_bar(ax, location=(0.8, 0.05)) plot_basemap_labels(ax, data_path, include_regions=False) # generate weight bins if plot_set['columns'][c] == 'tmda': column = plot_set['columns'][c] weights = [ int(str(record[column])) for iter_, record in mode_file.iterrows() if str(record[column]).isdigit() is True and int(str(record[column])) > 0 ] max_weight = max(weights) width_by_range = generate_weight_bins(weights, n_steps=7, width_step=0.02) # width_by_range = generate_weight_bins(weights, n_steps=9, width_step=0.01, interpolation='log') else: column = 'max_total_tons' weights = [ record[column] for iter_, record in mode_file.iterrows() ] max_weight = max(weights) width_by_range = generate_weight_bins(weights, n_steps=7, width_step=0.02) road_geoms_by_category = { 'national': [], 'province': [], 'rural': [], } column = plot_set['columns'][c] for iter_, record in mode_file.iterrows(): if column == 'tmda': if str(record[column]).isdigit() is False: val = 0 else: val = int(str(record[column])) else: val = record[column] if val > 0: cat = str(record['road_type']).lower().strip() if cat not in road_geoms_by_category: raise Exception geom = record.geometry buffered_geom = None for (nmin, nmax), width in width_by_range.items(): if nmin <= val and val < nmax: buffered_geom = geom.buffer(width) if buffered_geom is not None: road_geoms_by_category[cat].append(buffered_geom) else: print("Feature was outside range to plot", iter_) styles = OrderedDict([ ('national', Style(color='#e41a1c', zindex=9, label='National')), # red ('province', Style(color='#377eb8', zindex=8, label='Provincial')), # orange ('rural', Style(color='#4daf4a', zindex=7, label='Rural')), # blue ]) for cat, geoms in road_geoms_by_category.items(): cat_style = styles[cat] ax.add_geometries(geoms, crs=proj_lat_lon, linewidth=0, facecolor=cat_style.color, edgecolor='none', zorder=cat_style.zindex) x_l = -62.4 x_r = x_l + 0.4 base_y = -42.1 y_step = 0.8 y_text_nudge = 0.2 x_text_nudge = 0.2 ax.text(x_l, base_y + y_step - y_text_nudge, plot_set['legend_label'], horizontalalignment='left', transform=proj_lat_lon, size=10) divisor = plot_set['divisor'] significance_ndigits = plot_set['significance'] max_sig = [] for (i, ((nmin, nmax), line_style)) in enumerate(width_by_range.items()): if round(nmin / divisor, significance_ndigits) < round( nmax / divisor, significance_ndigits): max_sig.append(significance_ndigits) elif round(nmin / divisor, significance_ndigits + 1) < round( nmax / divisor, significance_ndigits + 1): max_sig.append(significance_ndigits + 1) elif round(nmin / divisor, significance_ndigits + 2) < round( nmax / divisor, significance_ndigits + 2): max_sig.append(significance_ndigits + 2) else: max_sig.append(significance_ndigits + 3) significance_ndigits = max(max_sig) for (i, ((nmin, nmax), width)) in enumerate(width_by_range.items()): y = base_y - (i * y_step) line = LineString([(x_l, y), (x_r, y)]).buffer(width) ax.add_geometries([line], crs=proj_lat_lon, linewidth=0, edgecolor='#000000', facecolor='#000000', zorder=2) if nmin == max_weight: value_template = '>{:.' + str(significance_ndigits) + 'f}' label = value_template.format( round(max_weight / divisor, significance_ndigits)) else: value_template = '{:.' + str(significance_ndigits) + \ 'f}-{:.' + str(significance_ndigits) + 'f}' label = value_template.format( round(nmin / divisor, significance_ndigits), round(nmax / divisor, significance_ndigits)) ax.text(x_r + x_text_nudge, y - y_text_nudge, label, horizontalalignment='left', transform=proj_lat_lon, size=10) plt.title('Max AADF - {}'.format(plot_set['title_cols'][c]), fontsize=10) legend_from_style_spec(ax, styles) output_file = os.path.join( config['paths']['figures'], 'road_flow-map-{}-{}-max-scale.png'.format( plot_set['file_tag'], column)) save_fig(output_file) plt.close()
# plt.ylabel("Count") # plt.title("Uncertainties for AVISO (GMSL retained)") # plt.savefig(plotdir+"AVISO_remGMSL0.png",dpi=150) # # Plot Historgram, GMSL removed # plt.figure() # plt.hist(nogmsl) # plt.xlabel(r"Uncertainty $%s"%uncertform) # plt.ylabel("Count") # plt.title("Uncertainties for AVISO (no GMSL)") # plt.savefig(plotdir+"AVISO_remGMSL1.png",dpi=150) vm = [-2, 2] # Visualize uncertainty maps fig, ax = plt.subplots( 1, 1, subplot_kw={'projection': ccrs.PlateCarree(central_longitude=180)}) ax = slutil.add_coast_grid(ax) pcm = plt.pcolormesh(lon5, lat5, gmsl, vmin=vm[0], vmax=vm[-1], cmap='copper', transform=ccrs.PlateCarree()) if takemedian: ax.set_title( r"Uncertainty (AVISO with GMSL) $(median(\sigma^{2}_{in,x})/median(\sigma^{2}_{out,x}))$" ) else: ax.set_title( r"Uncertainty (AVISO with GMSL) $(<\sigma^{2}_{in,x}>/<\sigma^{2}_{out,x}>)$"
def drawing(ax,proj,MARKER): # ====================================== ''' Draw a 2D vector plot. Option of vectors or stream function''' __version__ = "1.0" __author__ = "Quim Ballabrerera" __date__ = "May 2018" if not MARKER.show.get(): return west, east, south, north = ax.get_extent() xv = [] yv = [] lv = [] for i in range(MARKER.n): if MARKER.lon[i] > west and MARKER.lon[i] < east and \ MARKER.lat[i] > south and MARKER.lat[i] < north: xv.append(MARKER.lon[i]) yv.append(MARKER.lat[i]) lv.append(MARKER.label[i]) nn = len(xv) lmrk = None xpad = MARKER.PLOT.XPAD.get() ypad = MARKER.PLOT.YPAD.get() if nn > 0: if MARKER.textmode.get(): # Here, every marker is identified by its label for i in range(nn): ax.text(xpad+xv[i],ypad+yv[i],lv[i], ha=MARKER.PLOT.HA.get(), va=MARKER.PLOT.VA.get(), wrap=MARKER.PLOT.WRAP.get(), style=MARKER.PLOT.STYLE.get(), weight=MARKER.PLOT.WEIGHT.get(), color=MARKER.PLOT.TCOLOR.get(), size=MARKER.PLOT.TSIZE.get(), zorder=MARKER.PLOT.ZORDER.get(), rotation=MARKER.PLOT.ANGLE.get(), transform=ccrs.PlateCarree()) #transform=proj) if MARKER.PLOT.SHOW.get(): lines = [] labels = [] lmrk, = ax.plot(xv[i],yv[i],linestyle='', marker=marker_string(MARKER.PLOT.SYMBOL.get()), ms=MARKER.PLOT.SIZE.get(), label=MARKER.LABEL.get(), alpha=MARKER.PLOT.ALPHA.get(), color=MARKER.PLOT.COLOR.get(), zorder=MARKER.PLOT.ZORDER.get(), transform=ccrs.PlateCarree()) #transform=proj) # lines.append(lmrk) # legend = ax.legend(lines,['toto']) else: if MARKER.PLOT.SHOW.get(): lmrk, = ax.plot(xv,yv,linestyle='', marker=marker_string(MARKER.PLOT.SYMBOL.get()), ms=MARKER.PLOT.SIZE.get(), visible=MARKER.PLOT.SHOW.get(), label=MARKER.LABEL.get(), alpha=MARKER.PLOT.ALPHA.get(), color=MARKER.PLOT.COLOR.get(), zorder=MARKER.PLOT.ZORDER.get(), transform=ccrs.PlateCarree()) #transform=proj) return lmrk
def main(fname, plot_dir): ds = xr.open_dataset(fname, decode_times=False) lat = ds.latitude.values lon = ds.longitude.values bottom, top = lat[0], lat[-1] left, right = lon[0], lon[-1] fig = plt.figure(figsize=(20, 8)) plt.rcParams['font.family'] = "sans-serif" plt.rcParams['font.size'] = "14" plt.rcParams['font.sans-serif'] = "Helvetica" cmap = plt.cm.RdYlBu projection = ccrs.PlateCarree() axes_class = (GeoAxes, dict(map_projection=projection)) rows = 1 cols = 3 axgr = AxesGrid(fig, 111, axes_class=axes_class, nrows_ncols=(rows, cols), axes_pad=0.2, cbar_location='right', cbar_mode='single', cbar_pad=0.5, cbar_size='5%', label_mode='') # note the empty label_mode ppt_count = 0 for year in np.arange(1900, 2016): # 1970-2019 ppt_count += 1 year = 2016 for i, ax in enumerate(axgr): # add a subplot into the array of plots #ax = fig.add_subplot(rows, cols, i+1, projection=ccrs.PlateCarree()) plims = plot_map(ax, ds.pr[ppt_count + i, :, :], year, cmap, i, top, bottom, left, right) import cartopy.feature as cfeature states = cfeature.NaturalEarthFeature( category='cultural', name='admin_1_states_provinces_lines', scale='10m', facecolor='none') # plot state border SOURCE = 'Natural Earth' LICENSE = 'public domain' ax.add_feature(states, edgecolor='black', lw=0.5) year += 1 #bounds = np.linspace(0, 100, 9) #bounds = np.append(bounds, bounds[-1]+1) #norm = colors.BoundaryNorm(bounds, cmap.N) #cbar = axgr.cbar_axes[0].colorbar(plims, norm=norm, boundaries=bounds, ticks=bounds) cbar = axgr.cbar_axes[0].colorbar(plims) cbar.ax.set_title("Percentile", fontsize=16, pad=10) #for i, cax in enumerate(axgr.cbar_axes): # cax.set_yticks([0.5, 5, 15, 25, 50, 75, 85, 94.5, 99.5]) # cax.set_yticklabels(["0-1", "1-10", "10-20", "20-30", "30-70", "70-80", \ # "80-90", "90-99", "99-100"]) ofname = os.path.join(plot_dir, "AWAP_PPT_percentiles_2016_2018.png") fig.savefig(ofname, dpi=300, bbox_inches='tight', pad_inches=0.1) plt.show()
lat = pyg.gausslat(40) lon = pyg.regularlon(80, origin=-180) x = pyg.sin(2*np.pi * lon / 180.) * pyg.exp(-(lat - 30)**2 / (2*10**2)) y = pyg.cos(4*np.pi * lon / 180.) * pyg.exp(-(lat - 40)**2 / (4*10**2)) pyl.ioff() # Build CartopyAxis for a Lambert Conformal projection prj = dict(central_longitude=-90., central_latitude = 39.) ax = pyg.plot.CartopyAxes(projection = 'LambertConformal', prj_args = prj) ax.size = [6., 5.1] # Add ocean ax.add_feature(cartopy.feature.OCEAN) # Add quiver plot pyg.vquiver(x, y, axes=ax, width = 0.005) # Set plot title ax.setp(title = 'Lambert Conformal') # Set lat/lon grid ax.gridlines(xlocs = range(0, 361, 20), ylocs = range(-80, 81, 20)) # Set map extent to region over North America ax.set_extent([-140, -50, 10, 75], crs = ccrs.PlateCarree()) pyl.ion() ax.render(2)
def plot_map(ax, var, year, cmap, i, top, bottom, left, right): vmin, vmax = 0.0, 100.0 #top, bottom = 90, -90 #left, right = -180, 180 #top, bottom = -10, -44 #left, right = 112, 154 #print(np.nanmin(var), np.nanmax(var)) #bounds = [0.5, 5, 15, 25, 75, 85, 94.5, 99.5] bounds = np.linspace(0, 100 + 10, 10) #bounds = np.append(bounds, bounds[-1]+1) norm = colors.BoundaryNorm(bounds, cmap.N) img = ax.imshow(var * 100., origin='lower', transform=ccrs.PlateCarree(), interpolation='nearest', cmap=cmap, norm=norm, extent=(left, right, bottom, top), vmin=vmin, vmax=vmax) ax.coastlines(resolution='10m', linewidth=1.0, color='black') #ax.add_feature(cartopy.feature.OCEAN) ax.set_title("%d$-$%d" % (year, year + 1), fontsize=16) ax.set_xlim(140.7, 154) ax.set_ylim(-39.2, -28.1) if i == 0 or i >= 5: gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=0.5, color='black', alpha=0.5, linestyle='--') else: gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=False, linewidth=0.5, color='black', alpha=0.5, linestyle='--') #if i < 5: gl.xlabels_bottom = True if i > 1: gl.ylabels_left = False gl.xlabels_top = False gl.ylabels_right = False gl.xlines = False gl.ylines = False gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER gl.xlocator = mticker.FixedLocator([141, 145, 149, 153]) gl.ylocator = mticker.FixedLocator([-29, -32, -35, -38]) #if i == 0 : # ax.text(-0.2, 0.5, 'Latitude', va='bottom', ha='center', # rotation='vertical', rotation_mode='anchor', # transform=ax.transAxes, fontsize=16) #if i == 1: # ax.text(0.5, -0.2, 'Longitude', va='bottom', ha='center', # rotation='horizontal', rotation_mode='anchor', # transform=ax.transAxes, fontsize=16) return img
def draw_Crosssection_Wind_Temp_RH( cross_rh=None, cross_Temp=None, cross_u=None, cross_v=None,cross_terrain=None, gh=None, h_pos=None,st_point=None,ed_point=None,lw_ratio=None, levels=None,map_extent=(50, 150, 0, 65),model=None, output_dir=None): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) initTime = pd.to_datetime( str(cross_Temp['forecast_reference_time'].values)).replace(tzinfo=None).to_pydatetime() fcst_time=initTime+timedelta(hours=gh['forecast_period'].values[0]) fig = plt.figure(1, figsize=(lw_ratio[0],lw_ratio[1])) ax = plt.axes() cross_rh['data'].values[cross_rh['data'].values > 100]=100 # example 2: use the "fromList() method startcolor = '#1E90FF' #蓝色 midcolor = '#F1F1F1' #白色 endcolor = '#696969' #灰色 cmap2 = col.LinearSegmentedColormap.from_list('own2',['#1E90FF','#94D8F6','#F1F1F1','#BFBFBF','#696969']) # extra arguments are N=256, gamma=1.0 cm.register_cmap(cmap=cmap2) # we can skip name here as it was already defined rh_contour = ax.contourf(cross_rh['lon'], cross_rh['level'], cross_rh['data'], levels=np.arange(0, 101, 0.5), cmap=cm.get_cmap('own2')) rh_colorbar = fig.colorbar(rh_contour,ticks=[20,40,60,80,100]) # Plot potential temperature using contour, with some custom labeling Temp_contour = ax.contour(cross_Temp['lon'], cross_Temp['level'],cross_Temp['data'].values, levels=np.arange(-100, 100, 2), colors='#A0522D', linewidths=1) Temp_contour.clabel(np.arange(-100, 100, 2), fontsize=16, colors='#A0522D', inline=1, inline_spacing=8, fmt='%i', rightside_up=True, use_clabeltext=True) Temp_zero_contour = ax.contour(cross_Temp['lon'], cross_Temp['level'],cross_Temp['data'].values, levels=[0], colors='k', linewidths=3) try: Temp_zero_contour.clabel([0], fontsize=22, colors='k', inline=1, inline_spacing=8, fmt='%i', rightside_up=True, use_clabeltext=True) except: print('No Zero Line') wind_slc_vert = list(range(0, len(levels), 1)) wind_slc_horz = slice(5, 100, 5) ax.barbs(cross_u['lon'][wind_slc_horz], cross_u['level'][wind_slc_vert], cross_u['t_wind'][wind_slc_vert, wind_slc_horz]*2.5, cross_v['n_wind'][wind_slc_vert, wind_slc_horz]*2.5, color='k') startcolor = '#8B4513' #棕色 endcolor='#DAC2AD' #绿 cmap2 = col.LinearSegmentedColormap.from_list('own3',[endcolor,startcolor]) # extra arguments are N=256, gamma=1.0 cm.register_cmap(cmap=cmap2) terrain_contour = ax.contourf(cross_terrain['lon'], cross_terrain['level'], cross_terrain.values, levels=np.arange(0, 500, 1), cmap=cm.get_cmap('own3'),zorder=100) # Adjust the y-axis to be logarithmic ax.set_yscale('symlog') ax.set_yticklabels(np.arange(levels[0], levels[-1], -100)) ax.set_ylim(levels[0], levels[-1]) ax.set_yticks(np.arange(levels[0], levels[-1], -100)) # Define the CRS and inset axes data_crs = ccrs.PlateCarree() ax_inset = fig.add_axes(h_pos, projection=data_crs) ax_inset.set_extent(map_extent, crs=data_crs) # Plot geopotential height at 500 hPa using xarray's contour wrapper ax_inset.contour(gh['lon'], gh['lat'], np.squeeze(gh['data']), levels=np.arange(500, 600, 4), cmap='inferno') # Plot the path of the cross section endpoints = data_crs.transform_points(ccrs.Geodetic(), *np.vstack([st_point, ed_point]).transpose()[::-1]) ax_inset.scatter(endpoints[:, 0], endpoints[:, 1], c='k', zorder=2) ax_inset.plot(cross_u['lon'], cross_u['lat'], c='k', zorder=2) # Add geographic features ax_inset.coastlines() utl.add_china_map_2cartopy_public( ax_inset, name='province', edgecolor='black', lw=0.8, zorder=105) # Set the titles and axes labels ax_inset.set_title('') ax.set_title('['+model+'] '+'温度, 相对湿度, 沿剖面风', loc='right', fontsize=25) ax.set_ylabel('Pressure (hPa)') ax.set_xlabel('Longitude') rh_colorbar.set_label('Relative Humidity (%)') if(sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if(sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') bax=fig.add_axes([0.10,0.88,.25,.07],facecolor='#FFFFFFCC') bax.axis('off') #bax.set_yticks([]) #bax.set_xticks([]) bax.axis([0, 10, 0, 10]) plt.text(2.5, 7.5,'起报时间: '+initTime.strftime("%Y年%m月%d日%H时"),size=11) plt.text(2.5, 5,'预报时间: '+fcst_time.strftime("%Y年%m月%d日%H时"),size=11) plt.text(2.5, 2.5,'预报时效: '+str(int(gh['forecast_period'].values[0]))+'小时',size=11) plt.text(2.5, 0.5,'www.nmc.cn',size=11) utl.add_logo_extra_in_axes(pos=[0.1,0.88,.07,.07],which='nmc', size='Xlarge') # show figure if(output_dir != None): plt.savefig(output_dir+'温度_相对湿度_沿剖面风_预报_'+ '起报时间_'+initTime.strftime("%Y年%m月%d日%H时")+ '预报时效_'+str(int(gh['forecast_period'].values[0]))+'小时'+'.png', dpi=200,bbox_inches='tight') plt.close() if(output_dir == None): plt.show()
'lat': np.linspace(-89.5, 89.5, num=180), 'lon': np.linspace(0.5, 359.5, num=360), }, ) print('Output netCDF4') path_out = '../analysis/STDs/' outstatsfile = path_out + 'SSS_omip1-omip2_stats.nc' DS_stats.to_netcdf(path=outstatsfile, mode='w', format='NETCDF4') #J 描画 print('Start drawing') fig = plt.figure(figsize=(11, 8)) fig.suptitle(suptitle, fontsize=18) proj = ccrs.PlateCarree(central_longitude=-140.) lon_formatter = LongitudeFormatter(zero_direction_label=True) lat_formatter = LatitudeFormatter() bounds = [-0.4, -0.3, -0.2, -0.1, -0.06, -0.02, 0.02, 0.06, 0.1, 0.2, 0.3, 0.4] ticks_bounds = bounds cmap = 'RdBu_r' item = 'omip2-1' ax1 = plt.axes(projection=proj) da = DS_stats["mean"] da.plot(ax=ax1, cmap=cmap,
def proj_to_cartopy(proj): """ Converts a pyproj.Proj to a cartopy.crs.Projection (Code copied from https://github.com/fmaussion/salem) Parameters ---------- proj: pyproj.Proj the projection to convert Returns ------- a cartopy.crs.Projection object """ import cartopy.crs as ccrs try: from osgeo import osr has_gdal = True except ImportError: has_gdal = False proj = check_crs(proj) if proj.is_latlong(): return ccrs.PlateCarree() srs = proj.srs if has_gdal: # this is more robust, as srs could be anything (espg, etc.) s1 = osr.SpatialReference() s1.ImportFromProj4(proj.srs) srs = s1.ExportToProj4() km_proj = {'lon_0': 'central_longitude', 'lat_0': 'central_latitude', 'x_0': 'false_easting', 'y_0': 'false_northing', 'k': 'scale_factor', 'zone': 'zone', } km_globe = {'a': 'semimajor_axis', 'b': 'semiminor_axis', } km_std = {'lat_1': 'lat_1', 'lat_2': 'lat_2', } kw_proj = dict() kw_globe = dict() kw_std = dict() for s in srs.split('+'): s = s.split('=') if len(s) != 2: continue k = s[0].strip() v = s[1].strip() try: v = float(v) except: pass if k == 'proj': if v == 'tmerc': cl = ccrs.TransverseMercator if v == 'lcc': cl = ccrs.LambertConformal if v == 'merc': cl = ccrs.Mercator if v == 'utm': cl = ccrs.UTM if k in km_proj: kw_proj[km_proj[k]] = v if k in km_globe: kw_globe[km_globe[k]] = v if k in km_std: kw_std[km_std[k]] = v globe = None if kw_globe: globe = ccrs.Globe(**kw_globe) if kw_std: kw_proj['standard_parallels'] = (kw_std['lat_1'], kw_std['lat_2']) # mercatoooor if cl.__name__ == 'Mercator': kw_proj.pop('false_easting', None) kw_proj.pop('false_northing', None) return cl(globe=globe, **kw_proj)
def simple_plot(resource, variable='air', lat='lat', lon='lon', timestep=0, output=None): """ Generates a nice and simple plot. """ print("Plotting {}, timestep {} ...".format(resource, timestep)) pl_data = Dataset(resource) pl_val = pl_data.variables[variable][timestep, :, :] pl_lat = pl_data.variables[lat][:] pl_lon = pl_data.variables[lon][:] fig = plt.figure() fig.set_size_inches(18.5, 10.5, forward=True) ax = plt.axes(projection=ccrs.PlateCarree()) ax.coastlines(linewidth=0.8) ax.gridlines() vmin = np.min(pl_val) vmax = np.max(pl_val) levels = np.linspace(vmin, vmax, 30) cmap = get_cmap("RdBu_r") data_map = ax.contourf(pl_lon, pl_lat, pl_val, levels=levels, extend='both', cmap=cmap, projection=ccrs.PlateCarree()) data_cbar = plt.colorbar(data_map, extend='both', shrink=0.6) data_cont = ax.contour(pl_lon, pl_lat, pl_val, levels=levels, linewidths=0.5, colors="white", linestyles='dashed', projection=ccrs.PlateCarree()) plt.clabel(data_cont, inline=1, fmt='%1.0f') title = 'Simple plot for %s' % (variable) plt.title(title) plt.tight_layout() if not output: output = 'myplot_%s.png' % (uuid.uuid1()) plt.savefig(output) fig.clf() plt.close(fig) print("Plot written to {}".format(output)) return output
def process(self, sites, orography, land_mask): """ Using the constraints provided, find the nearest grid point neighbours to the given spot sites for the model/grid given by the input cubes. Returned is a cube that contains the defining characteristics of the spot sites (e.g. x coordinate, y coordinate, altitude) and the indices of the selected grid point neighbour. Args: sites (list of dict): A list of dictionaries defining the spot sites for which neighbours are to be found. e.g.: [{'altitude': 11.0, 'latitude': 57.867000579833984, 'longitude': -5.632999897003174, 'wmo_id': 3034}] orography (iris.cube.Cube): A cube of orography, used to obtain the grid point altitudes. land_mask (iris.cube.Cube): A land mask cube for the model/grid from which grid point neighbours are being selected, with land points set to one and sea points set to zero. Returns: iris.cube.Cube: A cube containing both the spot site information and for each the grid point indices of its nearest neighbour as per the imposed constraints. """ # Check if we are dealing with a global grid. self.global_coordinate_system = orography.coord(axis="x").circular # Exclude regional grids with spatial dimensions other than metres. if not self.global_coordinate_system: if not orography.coord(axis="x").units == "metres": msg = ("Cube spatial coordinates for regional grids must be" "in metres to match the defined search_radius.") raise ValueError(msg) # Ensure land_mask and orography are on the same grid. if not orography.dim_coords == land_mask.dim_coords: msg = "Orography and land_mask cubes are not on the same " "grid." raise ValueError(msg) # Enforce x-y coordinate order for input cubes. enforce_coordinate_ordering( orography, [ orography.coord(axis="x").name(), orography.coord(axis="y").name() ], ) enforce_coordinate_ordering( land_mask, [ land_mask.coord(axis="x").name(), land_mask.coord(axis="y").name() ], ) # Remap site coordinates on to coordinate system of the model grid. site_x_coords = np.array( [site[self.site_x_coordinate] for site in sites]) site_y_coords = np.array( [site[self.site_y_coordinate] for site in sites]) site_coords = self._transform_sites_coordinate_system( site_x_coords, site_y_coords, orography.coord_system().as_cartopy_crs()) # Exclude any sites falling outside the domain given by the cube and # notify the user. ( sites, site_coords, site_x_coords, site_y_coords, ) = self.check_sites_are_within_domain(sites, site_coords, site_x_coords, site_y_coords, orography) # Find nearest neighbour point using quick iris method. nearest_indices = self.get_nearest_indices(site_coords, orography) # Create an array containing site altitudes, using the nearest point # orography height for any that are unset. site_altitudes = np.array( [site.get(self.site_altitude, None) for site in sites]) site_altitudes = np.where( np.isnan(site_altitudes.astype(float)), orography.data[tuple(nearest_indices.T)], site_altitudes, ) # If further constraints are being applied, build a KD Tree which # includes points filtered by constraint. if self.land_constraint or self.minimum_dz: # Build the KDTree, an internal test for the land_constraint checks # whether to exclude sea points from the tree. tree, index_nodes = self.build_KDTree(land_mask) # Site coordinates made cartesian for global coordinate system if self.global_coordinate_system: site_coords = self.geocentric_cartesian( orography, site_coords[:, 0], site_coords[:, 1]) if not self.minimum_dz: # Query the tree for the nearest neighbour, in this case a land # neighbour is returned along with the distance to it. distances, node_indices = tree.query([site_coords]) # Look up the grid coordinates that correspond to the tree node (land_neighbour_indices, ) = index_nodes[node_indices] # Use the found land neighbour if it is within the # search_radius, otherwise use the nearest neighbour. distances = np.array([distances[0], distances[0]]).T nearest_indices = np.where( distances < self.search_radius, land_neighbour_indices, nearest_indices, ) else: # Query the tree for self.node_limit nearby neighbours. distances, node_indices = tree.query( [site_coords], distance_upper_bound=self.search_radius, k=self.node_limit, ) # Loop over the sites and for each choose the returned # neighbour with the minimum vertical displacement. for index, (distance, indices) in enumerate( zip(distances[0], node_indices[0])): grid_point = self.select_minimum_dz( orography, site_altitudes[index], index_nodes, distance, indices) # None is returned if the tree query returned no neighbours # within the search radius. if grid_point is not None: nearest_indices[index] = grid_point # Calculate the vertical displacements between the chosen grid point # and the spot site. vertical_displacements = (site_altitudes - orography.data[tuple(nearest_indices.T)]) # Create a list of WMO IDs if available. These are stored as strings # to accommodate the use of 'None' for unset IDs. wmo_ids = [str(site.get("wmo_id", None)) for site in sites] # Construct a name to describe the neighbour finding method employed method_name = self.neighbour_finding_method_name() # Create an array of indices and displacements to return data = np.stack( (nearest_indices[:, 0], nearest_indices[:, 1], vertical_displacements), axis=0, ) data = np.expand_dims(data, 0).astype(np.float32) # Regardless of input sitelist coordinate system, the site coordinates # are stored as latitudes and longitudes in the neighbour cube. if self.site_coordinate_system != ccrs.PlateCarree(): lon_lats = self._transform_sites_coordinate_system( site_x_coords, site_y_coords, ccrs.PlateCarree()) longitudes = lon_lats[:, 0] latitudes = lon_lats[:, 1] else: longitudes = site_x_coords latitudes = site_y_coords # Create a cube of neighbours neighbour_cube = build_spotdata_cube( data, "grid_neighbours", 1, site_altitudes.astype(np.float32), latitudes.astype(np.float32), longitudes.astype(np.float32), wmo_ids, neighbour_methods=[method_name], grid_attributes=["x_index", "y_index", "vertical_displacement"], ) # Add a hash attribute based on the model grid to ensure the neighbour # cube is only used with a compatible grid. grid_hash = create_coordinate_hash(orography) neighbour_cube.attributes["model_grid_hash"] = grid_hash return neighbour_cube
crs=projection) '''zero_direction_label=True 有度的标识,False则去掉''' lon_formatter = LongitudeFormatter(zero_direction_label=True) lat_formatter = LatitudeFormatter() ax.xaxis.set_major_formatter(lon_formatter) ax.yaxis.set_major_formatter(lat_formatter) '''添加网格线''' #gl = ax.gridlines() #ax.grid() return ax #============================================================================== # 设置常量 projection = ccrs.PlateCarree() resolution = '110m' lonstart = 60 lonstop = 360 latstart = -30 latstop = 90 box = np.array([lonstart, lonstop, latstart, latstop]) # x,y轴标签个数 xnum = 6 ynum = 5 # nrows = 2 ncols = 1 # prob_level levels_prob = [0., 0.95, 1.0] subtitles = ['a) EAWIM', 'b) EAWMIres']