def _plot_vel_surface(ax, plot_data, bathy, sections=None): ax.quiver( plot_data.gridX[::5], plot_data.gridY[::5], plot_data.U_surface[::5, ::5], plot_data.V_surface[::5, ::5], scale=20, ) if sections is not None: for section in zip(*sections): ax.plot(section[1][:2], (section[0], section[0]), "r--", linewidth=2) viz_tools.plot_land_mask(ax, bathy, color="burlywood") viz_tools.plot_coastline(ax, bathy)
def test_plot_land_mask_color_arg(self): axes, bathy = Mock(), Mock() bathy.variables = {'Bathymetry': Mock()} contour_fills = viz_tools.plot_land_mask(axes, bathy, color='red') axes.contourf.assert_called_once_with(bathy.variables['Bathymetry'], [-0.01, 0.01], colors='red') assert contour_fills == axes.contourf()
def _plot_ssh_map(ax_map, plot_data, place, theme): contour_intervals = [ -1, -0.5, 0.5, 1, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2, 2.4, 2.6, ] mesh = ax_map.contourf( plot_data.max_ssh_field, contour_intervals, cmap="YlOrRd", extend="both", alpha=0.6, ) ax_map.contour(plot_data.max_ssh_field, contour_intervals, colors="black", linestyles="--") cbar = plt.colorbar(mesh, ax=ax_map) j, i = PLACES[place]["NEMO grid ji"] ax_map.plot( i, j, marker="o", markersize=10, markeredgewidth=3, markerfacecolor=theme.COLOURS["marker"]["place"]["facecolor"], markeredgecolor=theme.COLOURS["marker"]["place"]["edgecolor"], ) viz_tools.plot_coastline(ax_map, plot_data.bathy) viz_tools.plot_land_mask(ax_map, plot_data.bathy, color=theme.COLOURS["land"]) _ssh_map_axis_labels(ax_map, place, plot_data, theme) _ssh_map_cbar_labels(cbar, contour_intervals, theme)
def test_plot_land_mask_isobath(self): axes, bathy = Mock(), Mock() bathy.variables = {'Bathymetry': Mock()} contour_fills = viz_tools.plot_land_mask(axes, bathy, isobath=42.42) args, kwargs = axes.contourf.call_args assert args[0] == bathy.variables['Bathymetry'] np.testing.assert_almost_equal(args[1], [-0.01, 42.43]) assert kwargs == {'colors': 'black'} assert contour_fills == axes.contourf()
def _plot_ssh_map(ax, plot_data, place, theme): contour_intervals = [ -1, -0.5, 0.5, 1, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2, 2.4, 2.6 ] mesh = ax.contourf(plot_data.ssh_max_field, contour_intervals, cmap='nipy_spectral', extend='both', alpha=0.6) ax.contour(plot_data.ssh_max_field, contour_intervals, colors='black', linestyles='--') cbar = plt.colorbar(mesh, ax=ax) viz_tools.plot_coastline(ax, plot_data.bathy) viz_tools.plot_land_mask(ax, plot_data.bathy, color=theme.COLOURS['land']) _ssh_map_axis_labels(ax, place, plot_data, theme) _ssh_map_cbar_labels(cbar, contour_intervals, theme)
def plot_CODAR_ellipse(ax, lons, lats, const, datastruc, depths, grid, step=3, scale=0.08, baroclinic=False, depth_level=0, barotropic=False, isobaths=[5, 20]): """Plot ellipses over the CODAR region""" major, minor, pha, inc = get_constituent(const, datastruc) if baroclinic: major = major[:, :, depth_level] minor = minor[:, :, depth_level] inc = inc[:, :, depth_level] title_str = 'baroclinic {0:.3g} m'.format(depths[depth_level][0]) elif barotropic: title_str = 'barotropic' else: title_str = 'surface' for i in np.arange(0, lons.shape[0], step): for j in np.arange(0, lats.shape[-1], step): if major[i, j]: plot_ellipse(lons[i, j], lats[i, j], inc[i, j], major[i, j], minor[i, j], ax, scale) ax.set_title('{} {} tidal ellipses'.format(const, title_str)) ax.set_ylabel('Latitude (degrees N)') ax.set_xlabel('Longitude (degrees W)') viz_tools.plot_land_mask(ax, grid, coords='map') for isobath in isobaths: viz_tools.plot_coastline(ax, grid, coords='map', isobath=isobath)
def test_plot_land_mask_map_coords(self): axes, bathy = Mock(), Mock() bathy.variables = { 'Bathymetry': Mock(), 'nav_lat': Mock(), 'nav_lon': Mock(), } contour_fills = viz_tools.plot_land_mask(axes, bathy, coords='map') axes.contourf.assert_called_once_with(bathy.variables['nav_lon'], bathy.variables['nav_lat'], bathy.variables['Bathymetry'], [-0.01, 0.01], colors='black') assert contour_fills == axes.contourf()
def test_plot_land_mask_grid_coords_slice(self): axes, bathy = Mock(), Mock() bathy.variables = {'Bathymetry': MagicMock(spec=nc.Variable)} xslice = np.arange(250, 370) yslice = np.arange(200, 320) contour_fills = viz_tools.plot_land_mask(axes, bathy, xslice=xslice, yslice=yslice) axes.contourf.assert_called_once_with( xslice, yslice, bathy.variables['Bathymetry'][yslice, xslice].data, [-0.01, 0.01], colors='black') assert contour_fills == axes.contourf()
def VENUS_location(grid_B, figsize=(10, 10)): """Plots the location of the VENUS Central, East and DDL nodes as well as Vancouver as a reference on a bathymetry map. :arg grid_B: Bathymetry dataset for the Salish Sea NEMO model. :type grid_B: :class:`netCDF4.Dataset` :arg figsize: Figure size (width, height) in inches. :type figsize: 2-tuple :returns: matplotlib figure object instance (fig). """ lats = grid_B.variables['nav_lat'][:] lons = grid_B.variables['nav_lon'][:] bathy = grid_B.variables['Bathymetry'][:] levels = np.arange(0, 470, 50) fig, ax = plt.subplots(1, 1, figsize=figsize) fig.patch.set_facecolor('#2B3E50') cmap = plt.get_cmap('winter_r') cmap.set_bad('burlywood') mesh = ax.contourf(lons, lats, bathy, levels, cmap=cmap, extend='both') cbar = fig.colorbar(mesh) viz_tools.plot_land_mask(ax, grid_B, coords='map', color='burlywood') viz_tools.plot_coastline(ax, grid_B, coords='map') viz_tools.set_aspect(ax) lon_c = SITES['VENUS']['Central']['lon'] lat_c = SITES['VENUS']['Central']['lat'] lon_e = SITES['VENUS']['East']['lon'] lat_e = SITES['VENUS']['East']['lat'] lon_d = SITES['VENUS']['ddl']['lon'] lat_d = SITES['VENUS']['ddl']['lat'] lon_v = SITES['Vancouver']['lon'] lat_v = SITES['Vancouver']['lat'] ax.plot( lon_c, lat_c, marker='D', color='Black', markersize=10, markeredgewidth=2) bbox_args = dict(boxstyle='square', facecolor='white', alpha=0.8) ax.annotate( 'Central', (lon_c - 0.11, lat_c + 0.04), fontsize=15, color='black', bbox=bbox_args) ax.plot( lon_e, lat_e, marker='D', color='Black', markersize=10, markeredgewidth=2) bbox_args = dict(boxstyle='square', facecolor='white', alpha=0.8) ax.annotate( 'East', (lon_e + 0.04, lat_e + 0.01), fontsize=15, color='black', bbox=bbox_args) ax.plot( lon_d, lat_d, marker='D', color='Black', markersize=10, markeredgewidth=2) bbox_args = dict(boxstyle='square', facecolor='white', alpha=0.8) ax.annotate( 'DDL', (lon_d + 0.01, lat_d + 0.05), fontsize=15, color='black', bbox=bbox_args) ax.plot( lon_v, lat_v, marker='D', color='DarkMagenta', markersize=10, markeredgewidth=2) bbox_args = dict(boxstyle='square', facecolor='white', alpha=0.8) ax.annotate( 'Vancouver', (lon_v - 0.15, lat_v + 0.04), fontsize=15, color='black', bbox=bbox_args) ax.set_xlim([-124.02, -123.02]) ax.set_ylim([48.5, 49.6]) plt.setp(plt.getp(cbar.ax.axes, 'yticklabels'), color='w') figures.axis_colors(ax, 'white') ax.set_xlabel('Longitude', **axis_font) ax.set_ylabel('Latitude', **axis_font) ax.set_title('VENUS Node Locations', **title_font) cbar.set_label('Depth [m]', **axis_font) return fig
def VENUS_location(grid_B, figsize=(10, 10)): """Plots the location of the VENUS Central, East and DDL nodes as well as Vancouver as a reference on a bathymetry map. :arg grid_B: Bathymetry dataset for the Salish Sea NEMO model. :type grid_B: :class:`netCDF4.Dataset` :arg figsize: Figure size (width, height) in inches. :type figsize: 2-tuple :returns: matplotlib figure object instance (fig). """ lats = grid_B.variables["nav_lat"][:] lons = grid_B.variables["nav_lon"][:] bathy = grid_B.variables["Bathymetry"][:] levels = np.arange(0, 470, 50) fig, ax = plt.subplots(1, 1, figsize=figsize) fig.patch.set_facecolor("#2B3E50") cmap = plt.get_cmap("winter_r") cmap.set_bad("burlywood") mesh = ax.contourf(lons, lats, bathy, levels, cmap=cmap, extend="both") cbar = fig.colorbar(mesh) viz_tools.plot_land_mask(ax, grid_B, coords="map", color="burlywood") viz_tools.plot_coastline(ax, grid_B, coords="map") viz_tools.set_aspect(ax) lon_c = SITES["VENUS"]["Central"]["lon"] lat_c = SITES["VENUS"]["Central"]["lat"] lon_e = SITES["VENUS"]["East"]["lon"] lat_e = SITES["VENUS"]["East"]["lat"] lon_d = SITES["VENUS"]["ddl"]["lon"] lat_d = SITES["VENUS"]["ddl"]["lat"] lon_v = SITES["Vancouver"]["lon"] lat_v = SITES["Vancouver"]["lat"] ax.plot(lon_c, lat_c, marker="D", color="Black", markersize=10, markeredgewidth=2) bbox_args = dict(boxstyle="square", facecolor="white", alpha=0.8) ax.annotate( "Central", (lon_c - 0.11, lat_c + 0.04), fontsize=15, color="black", bbox=bbox_args, ) ax.plot(lon_e, lat_e, marker="D", color="Black", markersize=10, markeredgewidth=2) bbox_args = dict(boxstyle="square", facecolor="white", alpha=0.8) ax.annotate("East", (lon_e + 0.04, lat_e + 0.01), fontsize=15, color="black", bbox=bbox_args) ax.plot(lon_d, lat_d, marker="D", color="Black", markersize=10, markeredgewidth=2) bbox_args = dict(boxstyle="square", facecolor="white", alpha=0.8) ax.annotate("DDL", (lon_d + 0.01, lat_d + 0.05), fontsize=15, color="black", bbox=bbox_args) ax.plot(lon_v, lat_v, marker="D", color="DarkMagenta", markersize=10, markeredgewidth=2) bbox_args = dict(boxstyle="square", facecolor="white", alpha=0.8) ax.annotate( "Vancouver", (lon_v - 0.15, lat_v + 0.04), fontsize=15, color="black", bbox=bbox_args, ) ax.set_xlim([-124.02, -123.02]) ax.set_ylim([48.5, 49.6]) plt.setp(plt.getp(cbar.ax.axes, "yticklabels"), color="w") axis_colors(ax, "white") ax.set_xlabel("Longitude", **axis_font) ax.set_ylabel("Latitude", **axis_font) ax.set_title("VENUS Node Locations", **title_font) cbar.set_label("Depth [m]", **axis_font) return fig
def _make_figure_domain(coordf, bathyf, theme): """ Create surface currents tiled domain figure showing the boundary and labels of each tile. :param coordf: Path to Salish Sea NEMO model coordinates file. :type coordf: :py:class:`pathlib.Path` :param bathyf: Path to Salish Sea NEMO model bathymetry file. :type bathyf: :py:class:`pathlib.Path` :param theme: Module-like object that defines the style elements for the figure. See :py:mod:`nowcast.figures.website_theme` for an example. :returns: :py:class:`matplotlib.figure.Figure` and plot axes. """ if theme is None: fig = Figure(figsize=(8.5, 11), facecolor="white") else: fig = Figure(figsize=(5, 6), dpi=100, facecolor=theme.COLOURS["figure"]["facecolor"]) ax = fig.add_subplot(111) ax.grid(True) # Decorations title = "Salish Sea" x_label = "Longitude" y_label = "Latitude" if theme is None: ax.set_title(title, fontsize=10) ax.set_xlabel(x_label) ax.set_ylabel(y_label) else: ax.set_title( title, fontsize=10, color=theme.COLOURS["text"]["axis"], fontproperties=theme.FONTS["axis"], ) ax.set_xlabel( x_label, color=theme.COLOURS["text"]["axis"], fontproperties=theme.FONTS["axis"], ) ax.set_ylabel( y_label, color=theme.COLOURS["text"]["axis"], fontproperties=theme.FONTS["axis"], ) theme.set_axis_colors( ax) # Makes the x and y numbers and axis lines into near-white with netCDF4.Dataset(bathyf) as _dsBathy: viz_tools.plot_land_mask(ax, _dsBathy, coords="map", color="burlywood", zorder=-9) ax.set_rasterization_zorder(-1) viz_tools.plot_coastline(ax, _dsBathy, coords="map") with netCDF4.Dataset(coordf) as _dsCoord: coord_yt = _dsCoord.variables["gphit"][0, :, :] viz_tools.set_aspect(ax, coords="map", lats=coord_yt) _drawTile(tile_coords_dic, ax) return fig, ax
def test_plot_land_mask_no_yslice(self): axes, bathy = Mock(), Mock() bathy.variables = {'Bathymetry': Mock()} with pytest.raises(ValueError): viz_tools.plot_land_mask(axes, bathy, xslice=np.arange(250, 370))
def test_plot_land_mask_defaults_bathy_netCDF_obj(self, m_dataset): axes, bathy = Mock(), Mock() bathy.variables = {'Bathymetry': Mock()} viz_tools.plot_land_mask(axes, bathy) assert not m_dataset.called assert not m_dataset.close.called
def test_plot_land_mask_defaults_bathy_file(self, m_dataset): axes = Mock() viz_tools.plot_land_mask(axes, 'bathyfile') m_dataset.assert_called_once_with('bathyfile') m_dataset().close.assert_called_once_with()
def _makeTiles( t_index, dsU, dsV, dsCoord, dsMask, dsBathy, theme, tile_coords_dic, expansion_factor, ): """ Produce surface current tile figures for each tile at time index t_index """ units = dsU.variables["time_counter"].units calendar = dsU.variables["time_counter"].calendar maskU, maskV = _prepareVelocity(t_index, dsU, dsV, dsCoord, dsMask) coord_xt, coord_yt = _prepareCoordinates(dsCoord) k = 3 tiles = [] figs = [] for tile, values in tile_coords_dic.items(): x1, x2, y1, y2 = values[0], values[1], values[2], values[3] sec = dsU.variables["time_counter"][t_index] if theme is None: fig = Figure(figsize=(8.5, 11), facecolor="white") else: fig = Figure( figsize=(11, 9), facecolor=theme.COLOURS["figure"]["facecolor"] ) ax = fig.add_subplot(111) X, Y = coord_xt[::k, ::k].flatten(), coord_yt[::k, ::k].flatten() U, V = maskU[::k, ::k].flatten(), maskV[::k, ::k].flatten() i = numpy.logical_not(U.mask) XC, YC, UC, VC = X[i], Y[i], U[i].data, V[i].data # Add some vectors in the middle of the Atlantic to ensure we get at least one for each arrow size tempU = numpy.linspace(0, 5, 50) zeros = numpy.zeros(tempU.shape) XC = numpy.concatenate([XC, zeros]) YC = numpy.concatenate([YC, zeros]) UC = numpy.concatenate([UC, tempU]) VC = numpy.concatenate([VC, zeros]) SC = numpy.sqrt(UC ** 2 + VC ** 2) i = SC < 0.05 if numpy.any(i): UCC, VCC, XCC, YCC = _cut(UC, VC, XC, YC, i) ax.scatter(XCC, YCC, s=2, c="k") # Arrow parameters: list of tuples of (speed_min, speed_max, arrow_width, arrow_head_width) arrowparamslist = [ (0.05, 0.25, 0.003, 3.00), (0.25, 0.50, 0.005, 2.75), (0.50, 1.00, 0.007, 2.25), (1.00, 1.50, 0.009, 2.00), (1.50, 2.00, 0.011, 1.50), (2.00, 2.50, 0.013, 1.25), (2.50, 3.00, 0.015, 1.00), (3.00, 4.00, 0.017, 0.75), (4.00, 100, 0.020, 2.00), ] if theme is None: # Quiver key positions (x,y) relative to axes that spans [0,1]x[0,1] positionslist = [ (0.55, 1.14), (0.55, 1.10), (0.55, 1.06), (0.55, 1.02), (0.80, 1.18), (0.80, 1.14), (0.80, 1.10), (0.80, 1.06), (0.80, 1.02), ] FP = None ax.text(0.53, 1.17, r"$\bullet$ < 0.05 m/s", transform=ax.transAxes) else: # Quiver key positions (x,y) relative to axes that spans [0,1]x[0,1] positionslist = [ (1.05, 0.95), (1.05, 0.90), (1.05, 0.85), (1.05, 0.80), (1.05, 0.75), (1.05, 0.70), (1.05, 0.65), (1.05, 0.60), (1.05, 0.55), ] FP = theme.FONTS["axis"] fontsize = FP.get_size() - 4 ax.text( 1.03, 0.98, r"$\bullet$ < 0.05 m/s", color=theme.COLOURS["text"]["axis"], fontsize=fontsize, transform=ax.transAxes, ) # Draw each arrow for arrowparams, positions in zip(arrowparamslist, positionslist): _drawArrows(arrowparams, positions, UC, VC, XC, YC, SC, ax, theme, FP) ax.grid(True) # Use expansion factor to set axes limits dx = (x2 - x1) * expansion_factor dy = (y2 - y1) * expansion_factor ax.set_xlim([x1 - dx, x2 + dx]) ax.set_ylim([y1 - dy, y2 + dy]) # Decorations title = _createTileTitle(sec, units, calendar) + "\n" + tile x_label = "Longitude" y_label = "Latitude" if theme is None: title_notheme = "SalishSeaCast Surface Currents\n" + title + "\n" ax.set_title(title_notheme, fontsize=12, loc="left") ax.set_xlabel(x_label) ax.set_ylabel(y_label) else: ax.set_title( title, fontsize=10, color=theme.COLOURS["text"]["axis"], fontproperties=FP, ) ax.set_xlabel( x_label, fontsize=8, color=theme.COLOURS["text"]["axis"], fontproperties=FP, ) ax.set_ylabel( y_label, color=theme.COLOURS["text"]["axis"], fontproperties=FP ) theme.set_axis_colors( ax ) # Makes the x and y numbers and axis lines into near-white x_tick_loc = ax.get_xticks() x_tick_label = ["{:.1f}".format(q) for q in x_tick_loc] ax.set_xticklabels(x_tick_label, rotation=45) viz_tools.plot_land_mask( ax, dsBathy, coords="map", color="burlywood", zorder=-9 ) ax.set_rasterization_zorder(-1) viz_tools.plot_coastline(ax, dsBathy, coords="map") viz_tools.set_aspect(ax, coords="map", lats=coord_yt) tiles += [tile] figs += [fig] return figs, tiles