def plot_map(ax, cast, grid_B, xlims, ylims): """ Plot the location of cast lon/lat on a map. :arg ax: axis for plotting :type ax: axis object :arg cast: the observed cast :type cast: pandas DataFrame-like object :arg grid_B: model bathymetry :type grid_B: netCDF4 object :arg xlims: min/max longitudes, eg [-124,-123] :type xlims: 2-tuple :arg ylims: min/max latitudes, eg [48,49] :type ylims: 2-tuple """ cast.plot(x='Longitude Corrected (deg)', y='Latitude Corrected (deg)', kind='scatter', ax=ax) viz_tools.plot_coastline(ax, grid_B, coords='map') ax.set_xlim(xlims) ax.set_ylim(ylims) ax.set_title(cast.day.min().strftime('%Y-%m-%d'))
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_coastline_isobath(self): axes, bathy = Mock(), Mock() bathy.variables = {'Bathymetry': Mock()} contour_lines = viz_tools.plot_coastline(axes, bathy, isobath=42.42) axes.contour.assert_called_once_with(bathy.variables['Bathymetry'], [42.42], colors='black') assert contour_lines == axes.contour()
def test_plot_coastline_color_arg(self): axes, bathy = Mock(), Mock() bathy.variables = {'Bathymetry': Mock()} contour_lines = viz_tools.plot_coastline(axes, bathy, color='red') axes.contour.assert_called_once_with(bathy.variables['Bathymetry'], [0], colors='red') assert contour_lines == axes.contour()
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 _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 monthly_means(lighthouse, grid_B, smin=28, smax=33, tmin=6, tmax=12): """Plot the monthly mean temperature and salinity at a lighthouse :arg lighthouse: the lighthouse name :type lighthouse: string :arg grid_B: NEMO bathymetry grid :type grid_B: netCDF4 handle :arg smin: minumum salinity for axis limits :type smin: float :arg smax: maximium salinity for axis limits :type smax: float :arg tmin: minumum temperature for axis limits :type tmin: float :arg tmax: maximium temperature for axis limits :type tmax: float :returns: fig, a figure object """ data, lat, lon = load_lighthouse(LIGHTHOUSES[lighthouse]) fig, axs = plt.subplots(1, 3, figsize=(15, 5)) grouped = data.groupby(['Month']) mean = grouped.apply(np.mean) ax = axs[0] mean.plot(y='Salinity(psu)', ax=ax) ax.set_ylim([smin, smax]) ax.set_title('{} Monthly Mean Observed Salinity'.format(lighthouse)) ax2 = axs[1] mean.plot(y='Temperature(C)', ax=ax2) ax2.set_ylim([tmin, tmax]) ax2.set_title('{} Monthly Mean Observed Temperature'.format(lighthouse)) # plot map axm = axs[2] axm.plot(lon, lat, 'o') viz_tools.plot_coastline(axm, grid_B, coords='map') return fig
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_coastline_map_coords(self): axes, bathy = Mock(), Mock() bathy.variables = { 'Bathymetry': Mock(), 'nav_lat': Mock(), 'nav_lon': Mock(), } contour_lines = viz_tools.plot_coastline(axes, bathy, coords='map') axes.contour.assert_called_once_with(bathy.variables['nav_lon'], bathy.variables['nav_lat'], bathy.variables['Bathymetry'], [0], colors='black') assert contour_lines == axes.contour()
def test_plot_coastline_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_lines = viz_tools.plot_coastline(axes, bathy, xslice=xslice, yslice=yslice) axes.contour.assert_called_once_with( xslice, yslice, bathy.variables['Bathymetry'][yslice, xslice].data, [0], colors='black') assert contour_lines == axes.contour()
def compare_cast_hourly(month, model_year, field, data_obs, model_path, xmin=-124, xmax=-122, ymin=48, ymax=50, zmin=0, zmax=300, vmin=10, vmax=32): """Comparison between model and observations at every cast in a given month Model daily average is compared witth houlry std errors """ # Load model grid grid = '/data/nsoontie/MEOPAR/NEMO-forcing/grid/bathy_meter_SalishSea2.nc' f = nc.Dataset(grid) bathy = f.variables['Bathymetry'][:] X = f.variables['nav_lon'][:] Y = f.variables['nav_lat'][:] mesh = '/data/nsoontie/MEOPAR/NEMO-forcing/grid/mesh_mask_SalishSea2.nc' g = nc.Dataset(mesh) depth_mod = g.variables['gdept_0'][0, :] # Model variables if field == 'Salinity': model_field = 'vosaline' elif field == 'Temperature': model_field = 'votemper' # plot obs and model data_m = data_obs[data_obs['Month'] == month] num_casts = len(data_m.index) fig, axs = plt.subplots(num_casts, 2, figsize=(10, 3.5 * num_casts)) cast = 0 for dep_obs, var_obs, lon, lat, day, year in zip( data_m['Depth'], data_m[field], data_m['Longitude'], data_m['Latitude'], data_m['Day'], data_m['Year']): # model grid points try: ax = axs[cast, 0] axm = axs[cast, 1] except IndexError: ax = axs[0] axm = axs[1] j, i = tidetools.find_closest_model_point(lon, lat, X, Y, bathy) date = datetime.datetime(year, month, day) if date >= FIRST_NOWCAST: hourly_grid = get_hourly_grid(date, model_path) depth_mod = hourly_grid.variables['deptht'][:] max_h, min_h, var_plot = calculate_hourly_ext( model_field, hourly_grid, j, i) else: var_model = early_model_data(date, j, i, '1h', 'grid_T', model_field, model_path) var_plot = np.mean(var_model, axis=0) min_h = np.min(var_model, axis=0) max_h = np.max(var_model, axis=0) # plot model ax.plot(var_plot, depth_mod, '-b', label='daily mean', alpha=0.5) ax.plot(max_h, depth_mod, 'k--', label='daily max') ax.plot(min_h, depth_mod, 'k:', label='daily min') # plot observations and location on map ax.plot(var_obs, dep_obs, '-*r', label='obs') axm.plot(lon, lat, '*r') # Set plot axis and labels ax.set_ylim([zmax, zmin]) ax.set_xlim([vmin, vmax]) ax.set_ylabel('Depth [m]') ax.set_xlabel(field) # plot mode coastline viz_tools.plot_coastline(axm, f, coords='map') axm.set_ylim([ymin, ymax]) axm.set_xlim([xmin, xmax]) axm.set_title('{}-{}-{}'.format(year, month, day)) # legend ax.legend(loc=0) cast = cast + 1 return fig
def compare_cast_model(month, model_year, field, data_obs, model_path, xmin=-124, xmax=-122, ymin=48, ymax=50, zmin=0, zmax=300, vmin=10, vmax=32, x=7): """Comparison between model and observations at every cast in a given month Model is compared x days before and after cast date """ # Load model grid grid = '/data/nsoontie/MEOPAR/NEMO-forcing/grid/bathy_meter_SalishSea2.nc' f = nc.Dataset(grid) bathy = f.variables['Bathymetry'][:] X = f.variables['nav_lon'][:] Y = f.variables['nav_lat'][:] # date ranges based on month and model_year date = datetime.datetime(model_year, month, 1) sdt = date - datetime.timedelta(days=31) edt = date + datetime.timedelta(days=60) # Model variables and nowcast/spinup? if field == 'Salinity': model_field = 'vosaline' elif field == 'Temperatute': model_field = 'votemper' # Is this a nowcast? if model_year == 2014 or model_year == 2015: nowcast_flag = True else: nowcast_flag = False # load model variables depth_mod, var_mod, dates_mod = load_model(model_path, sdt, edt, model_field, nowcast_flag=nowcast_flag) # plot obs and model data_m = data_obs[data_obs['Month'] == month] num_casts = len(data_m.index) fig, axs = plt.subplots(num_casts, 2, figsize=(10, 3.5 * num_casts)) cast = 0 for dep_obs, var_obs, lon, lat, day, year in zip( data_m['Depth'], data_m[field], data_m['Longitude'], data_m['Latitude'], data_m['Day'], data_m['Year']): # model grid points try: ax = axs[cast, 0] axm = axs[cast, 1] except IndexError: ax = axs[0] axm = axs[1] [j, i] = tidetools.find_closest_model_point(lon, lat, X, Y, bathy) # model time index t_ind = [] for count, date in enumerate(dates_mod): if date.day == day: if date.month == month: t_ind.append(count) t_ind.append(count - x) # x days earlier t_ind.append(count + x) # x days later labels = [ 'same day', '{} days earlier'.format(x), '{} days later'.format(x) ] colors = ['b', 'g', 'k'] for ii, t in enumerate(t_ind): try: var_plot = var_mod[t, :, j, i] var_plot = np.ma.masked_values(var_plot, 0) if j: ax.plot(var_plot, depth_mod, '-b', color=colors[ii], label=labels[ii], alpha=0.5) except IndexError: print('No model data for {}/{}, ' '{}'.format(day, month, labels[ii])) # plot observations and location on map ax.plot(var_obs, dep_obs, '-*r', label='obs') axm.plot(lon, lat, '*r') # Set plot axis and labels ax.set_ylim([zmax, zmin]) ax.set_xlim([vmin, vmax]) ax.set_ylabel('Depth [m]') ax.set_xlabel(field) # plot mode coastline viz_tools.plot_coastline(axm, f, coords='map') axm.set_ylim([ymin, ymax]) axm.set_xlim([xmin, xmax]) axm.set_title('{}-{}-{}'.format(year, month, day)) # legend ax.legend(loc=0) cast = cast + 1 return fig
def compare_model_obs(month, model_year, field, data_obs, model_path, xmin=-124, xmax=-122, ymin=48, ymax=50, zmin=0, zmax=300, vmin=10, vmax=32): """Compares the observations from WOD with model output on the same day and at a close grid point. Comparisons are during single month. field is compared ('Temperature' or 'Salinity' ) Observations stored in data_obs (DataFrame) Model_path defines where the model data is stored(can be nowcast or spinup) """ # Load model grid grid = '/data/nsoontie/MEOPAR/NEMO-forcing/grid/bathy_meter_SalishSea2.nc' f = nc.Dataset(grid) bathy = f.variables['Bathymetry'][:] X = f.variables['nav_lon'][:] Y = f.variables['nav_lat'][:] fig, [ax, axm] = plt.subplots(1, 2, figsize=(10, 3)) # date ranges based on month and model_year sdt = datetime.datetime(model_year, month, 1) edt = sdt + datetime.timedelta(days=31) # Model variables and nowcast/spinup? if field == 'Salinity': model_field = 'vosaline' elif field == 'Temperatute': model_field = 'votemper' # Is this a nowcast? if model_year == 2014 or model_year == 2015: nowcast_flag = True title = 'Nowcast' else: nowcast_flag = False title = 'Spinup' # load model variables depth_mod, var_mod, dates_mod = load_model(model_path, sdt, edt, model_field, nowcast_flag=nowcast_flag) # plot obs and model data_m = data_obs[data_obs['Month'] == month] for dep_obs, var_obs, lon, lat, day in zip(data_m['Depth'], data_m[field], data_m['Longitude'], data_m['Latitude'], data_m['Day']): # model grid points [j, i] = tidetools.find_closest_model_point(lon, lat, X, Y, bathy) # model time index t_ind = [] for count, date in enumerate(dates_mod): if date.month == month: if date.day == day: t_ind = count var_plot = var_mod[t_ind, :, j, i] var_plot = np.ma.masked_values(var_plot, 0) ax.plot(var_obs, dep_obs, '-*r', label='obs', alpha=0.5) if j: try: ax.plot(var_plot, depth_mod, '-ob', label='model', alpha=0.5) except ValueError: print('No model data for {}/{}'.format(day, month)) # plot location on map axm.plot(lon, lat, '*r') # Set plot axis and labels ax.set_ylim([zmax, zmin]) ax.set_xlim([vmin, vmax]) ax.set_title(title) ax.set_ylabel('Depth [m]') ax.set_xlabel(field) # plot mode coastline viz_tools.plot_coastline(axm, f, coords='map') axm.set_ylim([ymin, ymax]) axm.set_xlim([xmin, xmax]) axm.set_title('Month {}'.format(month)) # fake the legend simObs, = ax.plot(-1, 0, 'r*') simMod, = ax.plot(-1, 0, 'bo') ax.legend([simObs, simMod], ['obs', 'model'], loc=0) 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 compare_ONC_model(csvfilename, sdt, edt, grid_B, results_home, period='1h', interp=False, smin=30, smax=35, tmin=8, tmax=12, teos_to_psu=False): """Comparison between ONC mooring data in a date range and model results. :arg csvfilename: The file with the ONC data :type csvfilename: string :arg sdt: the start date of the date range :type sdt: datetime object :arg edt: the end date of the date range :type edt: datetime object :arg grid_B: the model bathymetry :type grid_B: netCDF handle :arg results_home: the path to the model results :type results_home: string :arg interp: a flag to specify if model should be interpolated to depth or just use closest model grid point :type interp: boolean :arg smin: minimum salinity for axis :type smin: float :arg smax: maximum salinity for axis :type smax: float :arg tmin: minimum temperature for axis :type tmin: float :arg tmax: maximum salinity for axis :type tmax: float :arg teos_to_psu: flag to convert model TEOS-10 'reference' salinity practical salinity :type teos_to_psu: boolean :returns: figmap, fig - figure objects for the map and comaprisons plots """ # Observations data, lat, lon, depth = load_mooring_csv(csvfilename) # resample observations and isolate date range data = isolate_dates(data, sdt, edt) data = resample_obs(data, period) # Model files sal, times, mdepths = load_model_data(sdt, edt, grid_B, results_home, period, 'vosaline', lat, lon) temp, times, mdepths = load_model_data(sdt, edt, grid_B, results_home, period, 'votemper', lat, lon) # Align model vertically sal, temp, text = model_vertical_postion(sal, temp, mdepths, depth, interp) if teos_to_psu: sal = teos_tools.teos_psu(sal) # Plotting fig, axs = plt.subplots(2, 1, figsize=(10, 7)) # Salinity ax = axs[0] ax.plot(times, sal, label='model') qc_data = isolate_qc_data(data, 'Practical Salinity QC Flag ') obs_sal = qc_data['Practical Salinity (psu)'] ax.plot(qc_data['time'], obs_sal, label='observations') ax.plot([sdt, edt], [sal.mean(), sal.mean()], 'b--', label='model mean') ax.plot([sdt, edt], [obs_sal.mean(), obs_sal.mean()], 'g--', label='observed mean') ax.set_ylabel('Practical Salinity [psu]') # Temperature ax = axs[1] ax.plot(times, temp, label='model') qc_data = isolate_qc_data(data, 'Temperature QC Flag ') obs_temp = qc_data['Temperature (C)'] ax.plot(qc_data['time'], obs_temp, label='observations') ax.plot([sdt, edt], [temp.mean(), temp.mean()], 'b--', label='model mean') ax.plot([sdt, edt], [obs_temp.mean(), obs_temp.mean()], 'g--', label='observed mean') ax.set_ylabel('Temperature [C]') # Format figure title = '{} average - '.format(period) + text for ax, lims in zip(axs, [[smin, smax], [tmin, tmax]]): ax.set_xlim([sdt, edt]) ax.set_ylim(lims) ax.legend(loc=0) ax.grid() ax.set_title(title) # Plot map figmap, ax = plt.subplots(1, 1) viz_tools.plot_coastline(ax, grid_B, coords='map') ax.plot(lon, lat, 'o') return figmap, fig
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
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 test_plot_coastline_defaults_bathy_netCDF_obj(self, m_dataset): axes, bathy = Mock(), Mock() bathy.variables = {'Bathymetry': Mock()} viz_tools.plot_coastline(axes, bathy) assert not m_dataset.called assert not m_dataset.close.called
def test_plot_coastline_defaults_bathy_file(self, m_dataset): axes = Mock() viz_tools.plot_coastline(axes, 'bathyfile') m_dataset.assert_called_once_with('bathyfile') m_dataset().close.assert_called_once_with()
def test_plot_coastline_no_yslice(self): axes, bathy = Mock(), Mock() bathy.variables = {'Bathymetry': Mock()} with pytest.raises(ValueError): viz_tools.plot_coastline(axes, bathy, xslice=np.arange(250, 370))
def compare_JEMS_model(stn, sdt, edt, grid_B, results_home, smin=5, smax=31, tmin=8, tmax=12): """Comparison between all JEMS T+S data in a date range and model nowcasts. :arg stn: The JEMS station name :type stn: string :arg sdt: the start date of the date range :type sdt: datetime object :arg edt: the end date of the date range :type edt: datetime object :arg grid_B: the model bathymetry :type grid_B: netCDF handle :arg results_home: the path to the model results :type results_home: string :arg smin: minimum salinity for axis :type smin: float :arg smax: maximum salinity for axis :type smax: float :arg tmin: minimum temperature for axis :type tmin: float :arg tmax: maximum salinity for axis :type tmax: float :returns: figmap, fig - figure objects for the map and comaprisons plots """ # Observations lat = SITES[stn]['lat'] lon = SITES[stn]['lon'] data = load_JEMS_csv(stn) data = isolate_dates(data, sdt, edt) data = data.groupby('date') # Model grid X = grid_B.variables['nav_lon'][:] Y = grid_B.variables['nav_lat'][:] bathy = grid_B.variables['Bathymetry'][:] [j, i] = tidetools.find_closest_model_point(lon, lat, X, Y, bathy) # Set up loop and figure num = data.ngroups fig, axs = plt.subplots(num, 2, figsize=(10, 4*num)) try: for day, axS, axT in zip(data.groups, axs[:, 0], axs[:, 1]): plot_comparisons(day, axS, axT, results_home, data, stn, j, i) axS.set_xlim([smin, smax]) axS.set_ylim([SITES[stn]['depth'], 0]) axT.set_xlim([tmin, tmax]) axT.set_ylim([SITES[stn]['depth'], 0]) axS.set_xlabel('Salinity (psu)') axT.set_xlabel('Temperature (deg C)') except IndexError: day = data.groups.keys()[0] axS = axs[0] axT = axs[1] plot_comparisons(day, axS, axT, results_home, data, stn, j, i) axS.set_xlim([smin, smax]) axS.set_ylim([SITES[stn]['depth'], 0]) axT.set_xlim([tmin, tmax]) axT.set_ylim([SITES[stn]['depth'], 0]) axS.set_xlabel('Salinity (psu)') axT.set_xlabel('Temperature (deg C)') # map figmap, ax = plt.subplots(1, 1) viz_tools.plot_coastline(ax, grid_B, coords='map') ax.plot(lon, lat, 'o') ax.set_title(stn) return figmap, 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