def plottimeavADCP(grid_m, grid_o, day, station): """ This function plots a comparison of the time averaged velocities of the model and the observations. :arg grid_m: The model grid :type grid_m: neCDF4 dataset. :arg grid_o: The observational grid :type grid_o: dictionary :arg day: day of interest :type day: datetime object :arg station: Station of interest. Either 'Central' or 'East' or 'ddl' :type station: string :return: fig """ if station == 'Central': profile = [0, 290] elif station == 'East': profile = [0, 150] else: profile = [0, 150] # Get grids into unstaggered and masked velocities at the chose depths u_E, v_N, dep_t = load_vel(day, grid_m, 'model', station, profile) u, v, dep = load_vel(day, grid_o, 'observation', station, profile) # Begin figure fig, ([ax1, ax2]) = plt.subplots(1, 2, figsize=(8, 10), sharex=True) fig.patch.set_facecolor('#2B3E50') # Setting the date for title date = day.strftime('%d%b%y') velocities = [u_E[:, :-1], v_N[:, :-1]] vellast = [u_E[:, -2:], v_N[:, -2:]] veloobs = [u, v] axes = [ax1, ax2] direction = ['E/W', 'N/S'] for ax, vel, velo, lastvel, direc in zip( axes, velocities, veloobs, vellast, direction): ax.plot(np.nanmean(vel, axis=0), dep_t[:-1], label='Model') ax.plot(np.nanmean(velo, axis=1), dep[:], label='Observations') ax.plot(np.nanmean( lastvel, axis=0), dep_t[-2:], '--b', label='Bottom grid cell') ax.set_xlabel('Daily averaged velocity [m/s]', **axis_font) ax.set_ylabel('Depth [m]', **axis_font) figures.axis_colors(ax, 'gray') ax.set_title(f'{direc} velocities at VENUS {station}', **title_font) ax.grid() ax.set_ylim(profile) ax.set_xlim([-0.5, 0.5]) ax.invert_yaxis() ax1.legend(loc=0) return fig
def plotdepavADCP(grid_m, grid_o, day, station): """ This function plots a comparison of the depth averaged velocities of the model and the observations. :arg grid_m: The model grid :type grid_m: netCDF4 dataset. :arg grid_o: The observational grid :type grid_o: dictionary :arg day: day of interest :type day: datetime object :arg station: Station of interest. Either 'Central' or 'East' or 'ddl' :type station: string :return: fig """ if station == 'Central': profile = [40, 270] elif station == 'East': profile = [30, 150] else: profile = [25, 130] # Get grids into unstaggered and masked velocities at the chose depths u_E, v_N, dep_t = load_vel(day, grid_m, 'model', station, profile) u, v, dep = load_vel(day, grid_o, 'observation', station, profile) # Depth averaging center of water column uE_av = analyze.depth_average(u_E, dep_t, 1) vN_av = analyze.depth_average(v_N, dep_t, 1) u_av = analyze.depth_average(u, dep[::-1], 0) v_av = analyze.depth_average(v, dep[::-1], 0) # Begin figure fig, ([ax1, ax2]) = plt.subplots(2, 1, figsize=(15, 10), sharex=True) fig.patch.set_facecolor('#2B3E50') # Setting the date for title date = day.strftime('%d%b%y') timestep = 0.5 velocities = [uE_av, vN_av] veloobs = [u_av, v_av] axes = [ax1, ax2] direction = ['East/West', 'North/South'] for ax, vel, velo, direc in zip(axes, velocities, veloobs, direction): ax.plot(np.arange(0, 24, timestep/2), vel, label='Model') ax.plot(np.arange(0.25, 24, timestep), velo, label='Observations') ax.set_xlim([0, 24]) ax.set_ylabel('Velocity [m/s]', **axis_font) figures.axis_colors(ax, 'gray') ax.set_title( f'Depth Averaged ({profile[0]}-{profile[1]}m) {direc} velocities ' f'at VENUS {station} -{date}', **title_font) ax.grid() ax.set_ylim([-0.6, 0.6]) ax1.legend(loc=0) ax2.set_xlabel('Hour [UTC]') return fig
def plotADCP(grid_m, grid_o, day, station, profile): """ This function will plots the velocities on a colour map with depth of the model and observational values. data over a whole day at a particular station. :arg grid_m: The model grid :type grid_m: neCDF4 dataset. :arg grid_o: The observational grid :type grid_o: dictionary :arg day: day of interest :type day: datetime object :arg station: Station of interest. Either 'Central' or 'East' or 'ddl'. :type station: string :arg profile: the range of depths that will be looked at in meters. (ex. [min, max]) :type profile: list :return: fig """ # Get grids into unstaggered and masked velocities at the chose depths u_E, v_N, dep_t = load_vel(day, grid_m, 'model', station, profile) u, v, dep = load_vel(day, grid_o, 'observation', station, profile) # Begin figure fig, ([axmu, axou], [axmv, axov]) = plt.subplots( 2, 2, figsize=(20, 10), sharex=True) fig.patch.set_facecolor('#2B3E50') # Find the absolute maximum value between the model and observational # velocities to set the colorbar max_v = np.nanmax(abs(v)) max_u = np.nanmax(abs(u)) max_vm = np.nanmax(abs(v_N)) max_um = np.nanmax(abs(u_E)) max_speed = np.amax([max_v, max_u, max_vm, max_um]) vmax = np.ceil(max_speed*10)/10.0 vmin = - vmax step = 0.05 cs = np.arange(vmin, vmax + step, step) cmap = plt.get_cmap('bwr') # Setting the date for title date = day.strftime('%d%b%y') # Plotting the comparison between the model and the obs velocities increment = [0.25, 0.5, 0.25, 0.5] velocities = [u_E.transpose(), u, v_N.transpose(), v] axes = [axmu, axou, axmv, axov] depths = [dep_t, dep, dep_t, dep] names = ['Model', 'Observations', 'Model', 'Observations'] direction = ['East/West', 'East/West', 'North/South', 'North/South'] for ax, vel, timestep, depth, name, direc in zip( axes, velocities, increment, depths, names, direction): ax.invert_yaxis() mesh = ax.contourf( # The range below adjusts for the observations starting at 00:15 # and being in 30 minutes increments. np.arange(timestep-0.25, 24+timestep-0.25, timestep), depth[:], vel, cs, cmap=cmap) ax.set_ylim([profile[1], profile[0]]) ax.set_xlim([0.25, 23]) ax.set_ylabel('Depth [m]', **axis_font) figures.axis_colors(ax, 'gray') ax.set_title( f'{direc} {name} Velocities at VENUS {station} - {date}', **title_font) cbar_ax = fig.add_axes([0.95, 0.2, 0.03, 0.6]) cbar = fig.colorbar(mesh, cax=cbar_ax) plt.setp(plt.getp(cbar.ax.axes, 'yticklabels'), color='w') cbar.set_label('[m/s]', **axis_font) axmv.set_xlabel('Hour [UTC]', **axis_font) axov.set_xlabel('Hour [UTC]', **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') 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 plot_vel_NE_gridded(station, grid, figsize=(14, 10)): """Plots the hourly averaged North/South and East/West velocities at a chosen VENUS node station using data that is calculated every 15 minutes. :arg station: Name of the station ('East' or 'Central') :type station: string :arg grid: Quarter-hourly velocity and tracer results dataset from NEMO. :type grid: :class:`netCDF4.Dataset` :arg figsize: Figure size (width, height) in inches or 'default'. :type figsize: 2-tuple :returns: matplotlib figure object instance (fig). """ u_u = grid.variables['vozocrtx'] v_v = grid.variables['vomecrty'] w_w = grid.variables['vovecrtz'] dep_t = grid.variables['depthv'] dep_w = grid.variables['depthw'] t = grid.variables['time_counter'] dt = (t[1]-t[0])/3600. maxt = dt*t.shape[0] t_axis = np.arange(0, maxt, dt) u_E, v_N = unstag_rot(u_u, v_v) u_E = u_E[..., 0, 0] v_N = v_N[..., 0, 0] fig, (axu, axv, axw) = plt.subplots(3, 1, figsize=figsize, sharex=True) fig.patch.set_facecolor('#2B3E50') max_array = np.maximum(abs(v_N), abs(u_E)) max_speed = np.amax(max_array) vmax = max_speed vmin = - max_speed step = 0.03 # viz_tools.set_aspect(axu) timestamp = nc_tools.timestamp(grid, 0) cmap = plt.get_cmap('jet') dep_s = SITES['VENUS'][station]['depth'] axu.invert_yaxis() mesh = axu.contourf( t_axis, dep_t[:], u_E.transpose(), np.arange(vmin, vmax, step), cmap=cmap) cbar = fig.colorbar(mesh, ax=axu) axu.set_ylim([dep_s, 0]) axu.set_xlim([0, maxt]) axu.set_ylabel('Depth [m]', **axis_font) figures.axis_colors(axu, 'white') axu.set_title( f'East/West Velocities at VENUS {station} on ' f'{timestamp.format("DD-MMM-YYYY")}', **title_font) plt.setp(plt.getp(cbar.ax.axes, 'yticklabels'), color='w') cbar.set_label('[m/s]', **axis_font) axv.invert_yaxis() mesh = axv.contourf( t_axis, dep_t[:], v_N.transpose(), np.arange(vmin, vmax, step), cmap=cmap) cbar = fig.colorbar(mesh, ax=axv) axv.set_ylim([dep_s, 0]) axv.set_xlim([0, maxt]) axv.set_ylabel('Depth [m]', **axis_font) figures.axis_colors(axv, 'white') axv.set_title( f'North/South Velocities at VENUS {station} on ' f'{timestamp.format("DD-MMM-YYYY")}', **title_font) plt.setp(plt.getp(cbar.ax.axes, 'yticklabels'), color='w') cbar.set_label('[m/s]', **axis_font) axw.invert_yaxis() mesh = axw.contourf( t_axis, dep_w[:], w_w[:, :, 1, 1].transpose(), np.arange(vmin/70, vmax/70, step/80), cmap=cmap) cbar = fig.colorbar(mesh, ax=axw) axw.set_ylim([dep_s, 0]) axw.set_xlim([0, maxt]) axw.set_xlabel('Time [h]', **axis_font) axw.set_ylabel('Depth [m]', **axis_font) figures.axis_colors(axw, 'white') axw.set_title( f'Vertical Velocities at VENUS {station} on ' f'{timestamp.format("DD-MMM-YYYY")}', **title_font) plt.setp(plt.getp(cbar.ax.axes, 'yticklabels'), color='w') cbar.set_label('[m/s]', **axis_font) return fig
def compare_VENUS(station, grid_T, grid_B, figsize=(6, 10)): """Compares the model's temperature and salinity with observations from VENUS station. :arg station: Name of the station ('East' or 'Central') :type station: string :arg grid_T: Hourly tracer results dataset from NEMO. :type grid_T: :class:`netCDF4.Dataset` :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). """ # Time range t_orig, t_end, t = figures.get_model_time_variables(grid_T) # Bathymetry bathy, X, Y = tt.get_bathy_data(grid_B) # VENUS data fig, (ax_sal, ax_temp) = plt.subplots(2, 1, figsize=figsize, sharex=True) fig.patch.set_facecolor('#2B3E50') fig.autofmt_xdate() lon = SITES['VENUS'][station]['lon'] lat = SITES['VENUS'][station]['lat'] depth = SITES['VENUS'][station]['depth'] # Plotting observations plot_VENUS(ax_sal, ax_temp, station, t_orig, t_end) # Grid point of VENUS station [j, i] = geo_tools.find_closest_model_point( lon, lat, X, Y) # Model data sal = grid_T.variables['vosaline'][:, :, j, i] temp = grid_T.variables['votemper'][:, :, j, i] ds = grid_T.variables['deptht'] # Interpolating data salc = [] tempc = [] for ind in np.arange(0, sal.shape[0]): salc.append(figures.interpolate_depth(sal[ind, :], ds, depth)) tempc.append(figures.interpolate_depth(temp[ind, :], ds, depth)) # Plot model data ax_sal.plot(t, salc, '-b', label='Model') ax_temp.plot(t, tempc, '-b', label='Model') # Axis ax_sal.set_title(f'VENUS {station} - {t[0].strftime("%d-%b-%Y")}') ax_sal.set_ylim([29, 32]) ax_sal.set_ylabel('Practical Salinity [psu]', **axis_font) ax_sal.legend(loc=0) ax_temp.set_ylim([7, 13]) ax_temp.set_xlabel('Time [UTC]', **axis_font) ax_temp.set_ylabel('Temperature [deg C]', **axis_font) figures.axis_colors(ax_sal, 'gray') figures.axis_colors(ax_temp, 'gray') # Text box ax_temp.text(0.25, -0.3, 'Observations from Ocean Networks Canada', transform=ax_temp.transAxes, color='white') return fig
def salinity_ferry_route( ferry_data_dir, grid_T_hr, bathy, route_name, dmy, figsize=(20, 7.5), ): """Plot daily salinity comparisons between ferry observations and model results as well as ferry route with model salinity distribution. :arg str ferry_data_dir: storage file location for ONC ferry data. :arg grid_T_hr: Hourly tracer results dataset from NEMO. :type grid_T_hr: :class:`netCDF4.Dataset :arg bathy: model bathymetry :type bathy: numpy array :arg str route_name: route name of these three ferry routes respectively :arg str dmy: date in form ddmonyy :arg 2-tuple figsize: Figure size (width, height) in inches. :returns: matplotlib figure object instance (fig). """ # Grid region to plot si, ei = 200, 610 sj, ej = 20, 370 lons = grid_T_hr.variables['nav_lon'][si:ei, sj:ej] lats = grid_T_hr.variables['nav_lat'][si:ei, sj:ej] # Salinity calculated by NEMO and observed by ONC ferry package model_depth_level = 1 # 1.5 m ## TODO: model time step for salinity contour map should be calculated from ## ferry route time model_time_step = 3 # 02:30 UTC sal_hr = grid_T_hr.variables['vosaline'] ## TODO: Use mesh mask instead of 0 for masking sal_masked = np.ma.masked_values( sal_hr[model_time_step, model_depth_level, si:ei, sj:ej], 0) sal_t = teos_tools.psu_teos(sal_masked) sal_obs = ferry_salinity(ferry_data_dir, route_name, dmy) nemo_a, nemo_b = nemo_sal_route(grid_T_hr, bathy, route_name, sal_obs) fig, axs = plt.subplots(1, 2, figsize=figsize) axs[1].set_axis_bgcolor("burlywood") viz_tools.set_aspect(axs[1], coords='map', lats=lats) cmap = plt.get_cmap('plasma') axs[1].set_xlim(-124.5, -122.5) axs[1].set_ylim(48.3, 49.6) # Plot model salinity mesh = axs[1].contourf(lons, lats, sal_t, 20, cmap=cmap) cbar = plt.colorbar(mesh, ax=axs[1]) cbar.ax.axes.tick_params(labelcolor='w') cbar.set_label('Absolute Salinity [g/kg]', color='white', **axis_font) axs[1].set_title('Ferry Route: 3am[UTC] 1.5m model result ', **title_font) axs[1].set_xlabel('Longitude [°E]', **axis_font) axs[1].set_ylabel('Latitude [°N]', **axis_font) # Plot ferry route. axs[1].plot(sal_obs[1], sal_obs[2], 'black', linewidth=4) figures.axis_colors(axs[1], 'grey') # Add locations and markers on plot for orientation bbox_args = dict(boxstyle='square', facecolor='white', alpha=0.7) places = [ FERRY_ROUTES[route_name]['start']['terminal'], FERRY_ROUTES[route_name]['end']['terminal'], 'Vancouver' ] label_offsets = [0.04, -0.4, 0.09] for stn, loc in zip(places, label_offsets): axs[1].plot(*PLACES[stn]['lon lat'], marker='D', color='white', markersize=10, markeredgewidth=2) axs[1].annotate( stn, (PLACES[stn]['lon lat'][0] + loc, PLACES[stn]['lon lat'][1]), fontsize=15, color='black', bbox=bbox_args) # Set up model part of salinity comparison plot axs[0].plot(sal_obs[1], nemo_a, 'DodgerBlue', linewidth=2, label=f'{FERRY_ROUTES[route_name]["start"]["hour"]} am [UTC]') axs[0].plot( sal_obs[1], nemo_b, 'MediumBlue', linewidth=2, label=f'{FERRY_ROUTES[route_name]["start"]["hour"]+1} am [UTC]') # Observational component of salinity comparisons plot axs[0].plot(sal_obs[1], sal_obs[3], 'DarkGreen', linewidth=2, label="Observed") axs[0].text(0.25, -0.1, 'Observations from Ocean Networks Canada', transform=axs[0].transAxes, color='white') axs[0].set_xlim(-124, -123) axs[0].set_ylim(10, 32) axs[0].set_title('Surface Salinity: ' + dmy, **title_font) axs[0].set_xlabel('Longitude', **axis_font) axs[0].set_ylabel('Absolute Salinity [g/kg]', **axis_font) axs[0].legend(loc=3) axs[0].grid(axis='both') fig.patch.set_facecolor('#2B3E50') figures.axis_colors(axs[0], 'grey') return fig