def plot(self): figuresize = list(map(float, self.size.split("x"))) fig = plt.figure(figsize=figuresize, dpi=self.dpi) width = len(self.variables) if self.showmap: width += 1 # Shift graphs to the right gs = gridspec.GridSpec(2, width) subplot = 0 # Render point location if self.showmap: plt.subplot(gs[0, subplot]) subplot += 1 utils.point_plot(np.array([self.latitude, self.longitude])) if len(self.ids) > 1: plt.legend(self.ids, loc='best') plot_label = "" giops_name = "GIOPS" for idx, v in enumerate(self.variables): plt.subplot(gs[:, subplot]) subplot += 1 handles = [] legend = [] for i in range(0, len(self.forecast_data)): id_label = f"{self.ids[i]} " if len(self.ids) > 1 else "" form = '-' if self.observed_data[i, idx, :].count() < 3: form = 'o-' if self.error in ['climatology', 'observation']: if self.error == 'climatology': plot_label = gettext("Error wrt Climatology") handles.append( plt.plot( self.observed_data[i, idx, :] - self.climatology_data[i, idx, :], self.depths[i], form)) legend.append(f"{id_label} {gettext('Observed')}") data = self.climatology_data else: plot_label = gettext("Error wrt Observation") data = self.observed_data handles.append( plt.plot( self.forecast_data[i, idx, :] - data[i, idx, :], self.depths[i], form)) legend.append(f"{id_label} {giops_name}") for j, model_name in enumerate( self.additional_model_names): handles.append( plt.plot( self.additional_model_data[j, i, idx, :] - data[i, idx, :], self.depths[i], form)) legend.append(f"{id_label} {model_name}") if self.error == 'observation' and self.climatology: handles.append( plt.plot( self.climatology_data[i, idx, :] - self.observed_data[i, idx, :], self.depths[i], form)) legend.append(f"{id_label} {gettext('Climatology')}") lim = np.abs(plt.xlim()).max() plt.xlim([-lim, lim]) else: plot_label = gettext("Class 4") handles.append( plt.plot(self.observed_data[i, idx, :], self.depths[i], form)) legend.append("%s %s" % (id_label, gettext("Observed"))) handles.append( plt.plot(self.forecast_data[i, idx, :], self.depths[i], form)) legend.append(f"{id_label} {giops_name}") for j, model_name in enumerate( self.additional_model_names): handles.append( plt.plot(self.additional_model_data[j, i, idx, :], self.depths[i], form)) legend.append(f"{id_label} {model_name}") if self.climatology: handles.append( plt.plot(self.climatology_data[i, idx, :], self.depths[i], form)) legend.append(f"{id_label} {gettext('Climatology')}") plt.xlim([np.floor(plt.xlim()[0]), np.ceil(plt.xlim()[1])]) plt.gca().xaxis.set_label_position('top') plt.gca().xaxis.set_ticks_position('top') plt.xlabel(f"{v} ({utils.mathtext(self.variable_units[idx])})", fontsize=14) plt.gca().invert_yaxis() plt.ylabel(gettext(f"Depth ({utils.mathtext(self.depth_unit)})"), fontsize=14) plt.grid(True) leg = fig.legend([x[0] for x in handles], legend, loc='lower left', bbox_to_anchor=(0.05, 0.05)) for legobj in leg.legendHandles: legobj.set_linewidth(4.0) names = [ "{} ({:0.2f}, {:0.2f})".format(*x) for x in zip(self.ids, self.latitude, self.longitude) ] wrapped_names = "\n".join(wrap(", ".join(names), 60)) plt.suptitle(f"{wrapped_names}\n{plot_label}", fontsize=15) fig.tight_layout(pad=3, w_pad=4) fig.subplots_adjust(top=0.85) return super(Class4Plotter, self).plot(fig)
def plot(self): # Create base figure fig = plt.figure(figsize=self.figuresize, dpi=self.dpi) # Setup figure layout width = 2 if self.showmap else 1 # Scale TS Diagram to be double the size of location map width_ratios = [1, 3] if self.showmap else None # Create layout helper gs = gridspec.GridSpec(1, width, width_ratios=width_ratios) # Render point location if self.showmap: plt.subplot(gs[0, 0]) utils.point_plot(np.array([[x[0] for x in self.points], # Latitudes [x[1] for x in self.points]])) # Longitudes # Plot TS Diagram plt.subplot(gs[:, 1 if self.showmap else 0]) smin = np.amin(self.salinity) - (np.amin(self.salinity) * 0.01) smax = np.amax(self.salinity) + (np.amax(self.salinity) * 0.01) tmin = np.amin(self.temperature) - ( np.abs(np.amax(self.temperature) * 0.1)) tmax = np.amax(self.temperature) + ( np.abs(np.amax(self.temperature) * 0.1)) xdim = int(round((smax - smin) / 0.1 + 1, 0)) ydim = int(round((tmax - tmin) + 1, 0)) dens = np.zeros((ydim, xdim)) ti = np.linspace(0, ydim - 1, ydim) + tmin si = np.linspace(0, xdim - 1, xdim) * 0.1 + smin for j in range(0, int(ydim)): for i in range(0, int(xdim)): dens[j, i] = seawater.dens(si[i], ti[j], 0) dens -= 1000 CS = plt.contour(si, ti, dens, linestyles='dashed', colors='k') plt.clabel(CS, fontsize=15, inline=1, fmt=r"$\sigma_t = %1.1f$") for idx, _ in enumerate(self.temperature): plt.plot(self.salinity[idx], self.temperature[idx], '-') plt.xlabel(gettext("Salinity (PSU)"), fontsize=14) plt.ylabel(gettext("Temperature (Celsius)"), fontsize=14) if len(self.points) == 1: labels = [] for idx, d in enumerate(self.temperature_depths[0]): if np.ma.is_masked(self.temperature[0][idx]): break digits = max(np.ceil(np.log10(d)), 3) d = np.round(d, -int(digits - 1)) if d not in labels: labels.append(d) for idx2, _ in enumerate(self.temperature): plt.annotate( '{:.0f}m'.format(d), xy=(self.salinity[idx2][ idx], self.temperature[idx2][idx]), xytext=(15, -15), ha='left', textcoords='offset points', arrowprops=dict(arrowstyle='->') # , shrinkA=0) ) self.plot_legend(fig, self.names) if not self.plotTitle: plt.title(gettext("T/S Diagram for (%s)\n%s") % ( ", ".join(self.names), self.date_formatter(self.iso_timestamp)), fontsize=15 ) else: plt.title(self.plotTitle, fontsize=15) return super(TemperatureSalinityPlotter, self).plot(fig)
def plot(self): # Create base figure fig = plt.figure(figsize=self.figuresize(), dpi=self.dpi) # Setup figure layout width = len(self.variables) if self.showmap: width += 1 # Horizontally scale the actual plots by 2x the size of # the location map width_ratios = [1] [width_ratios.append(2) for w in range(0, width - 1)] else: width_ratios = None # Create layout helper gs = gridspec.GridSpec(1, width, width_ratios=width_ratios) subplot = 0 # Render point location if self.showmap: plt.subplot(gs[0, subplot]) subplot += 1 utils.point_plot( np.array([ [x[0] for x in self.points], # Latitudes [x[1] for x in self.points] ])) # Longitudes is_y_label_plotted = False # Create a subplot for each variable selected # Each subplot has all points plotted for idx, v in enumerate(self.variables): plt.subplot(gs[:, subplot]) plt.plot(self.data[:, idx, :].transpose(), self.depths[:, idx, :].transpose()) current_axis = plt.gca() current_axis.xaxis.set_label_position('top') current_axis.xaxis.set_ticks_position('top') current_axis.invert_yaxis() current_axis.grid(True) current_axis.set_xlabel("%s (%s)" % (self.variable_names[idx], utils.mathtext(self.variable_units[idx])), fontsize=14) # Put y-axis label on left-most graph (but after the point location) if not is_y_label_plotted and (subplot == 0 or subplot == 1): current_axis.set_ylabel(gettext("Depth (m)"), fontsize=14) is_y_label_plotted = True if self.compare: xlim = np.abs(plt.gca().get_xlim()).max() plt.gca().set_xlim([-xlim, xlim]) subplot += 1 self.plot_legend(fig, self.names) if self.plotTitle is None or self.plotTitle == "": plt.suptitle("%s(%s)\n%s\n%s" % (gettext("Profile for "), \ ", ".join(self.names), \ ", ".join(self.variable_names), \ self.date_formatter(self.timestamp)), \ fontsize=15) else: plt.suptitle(self.plotTitle, fontsize=15) fig.tight_layout() fig.subplots_adjust(top=(0.8)) return super(ProfilePlotter, self).plot(fig)
def plot(self): if self.scale: vmin = self.scale[0] vmax = self.scale[1] else: vmin, vmax = utils.normalize_scale( self.data, self.dataset_config.variable[self.variables[0]]) if self.cmap is None: self.cmap = colormap.find_colormap(self.variable_name) datenum = matplotlib.dates.date2num(self.times) if self.depth == 'all': size = list(map(float, self.size.split("x"))) numpoints = len(self.points) figuresize = (size[0], size[1] * numpoints) fig, ax = plt.subplots(numpoints, 1, sharex=True, figsize=figuresize, dpi=self.dpi) if not isinstance(ax, np.ndarray): ax = [ax] for idx, p in enumerate(self.points): d = self.data[idx, 0, :] dlim = np.ma.flatnotmasked_edges(d[0, :]) maxdepth = self.depths[dlim[1]].max() mindepth = self.depths[dlim[0]].min() c = ax[idx].pcolormesh(datenum, self.depths[:dlim[1] + 1], d[:, :dlim[1] + 1].transpose(), shading='gouraud', cmap=self.cmap, vmin=vmin, vmax=vmax) ax[idx].invert_yaxis() if maxdepth > LINEAR: ax[idx].set_yscale('symlog', linthreshy=LINEAR) ax[idx].yaxis.set_major_formatter(ScalarFormatter()) if maxdepth > LINEAR: l = 10**np.floor(np.log10(maxdepth)) ax[idx].set_ylim(np.ceil(maxdepth / l) * l, mindepth) ax[idx].set_yticks( list(ax[idx].get_yticks()) + [maxdepth, LINEAR]) else: ax[idx].set_ylim(maxdepth, mindepth) ax[idx].set_ylabel("Depth (%s)" % utils.mathtext(self.depth_unit)) ax[idx].xaxis_date() ax[idx].set_xlim(datenum[0], datenum[-1]) divider = make_axes_locatable(ax[idx]) cax = divider.append_axes("right", size="5%", pad=0.05) bar = plt.colorbar(c, cax=cax) bar.set_label("%s (%s)" % (self.variable_name.title(), utils.mathtext(self.variable_unit))) ax[idx].set_title("%s%s at %s" % (self.variable_name.title(), self.depth_label, self.names[idx])) plt.setp(ax[idx].get_xticklabels(), rotation=30) fig.autofmt_xdate() else: # Create base figure figure_size = self.figuresize figure_size[0] *= 1.5 if self.showmap else 1.0 fig = plt.figure(figsize=figure_size, dpi=self.dpi) # Setup figure layout width = 1 if self.showmap: width += 1 # Horizontally scale the actual plots by 2x the size of # the location map width_ratios = [1, 2] else: width_ratios = None # Create layout helper gs = gridspec.GridSpec(1, width, width_ratios=width_ratios) subplot = 0 # Render point location if self.showmap: plt.subplot(gs[0, 0]) subplot += 1 utils.point_plot( np.array([ [x[0] for x in self.points], # Latitudes [x[1] for x in self.points] ])) # Longitudes plt.subplot(gs[:, subplot]) plt.plot_date(datenum, np.squeeze(self.data), fmt='-', figure=fig, xdate=True) plt.ylabel( f"{self.variable_name.title()} ({utils.mathtext(self.variable_unit)})", fontsize=14) plt.ylim(vmin, vmax) # Title if self.plotTitle is None or self.plotTitle == "": wrapped_title = wrap( "%s%s at %s" % (self.variable_name.title(), self.depth_label, ", ".join(self.names)), 80) plt.title("\n".join(wrapped_title), fontsize=15) else: plt.title(self.plotTitle, fontsize=15) plt.gca().grid(True) fig.autofmt_xdate() self.plot_legend(fig, self.names) return super(TimeseriesPlotter, self).plot(fig)
def plot(self): # Create base figure fig = plt.figure(figsize=self.figuresize(), dpi=self.dpi) # Setup figure layout width = 2 if self.showmap else 1 # Scale TS Diagram to be double the size of location map width_ratios = [1, 3] if self.showmap else None # Create layout helper gs = gridspec.GridSpec(1, width, width_ratios=width_ratios) # Render point location if self.showmap: plt.subplot(gs[0, 0]) utils.point_plot( np.array([ [x[0] for x in self.points], # Latitudes [x[1] for x in self.points] ])) # Longitudes # Plot Sound Speed profile plt.subplot(gs[:, 1 if self.showmap else 0]) ax = plt.gca() for i, ss in enumerate(self.sspeed): ax.plot(ss, self.temperature_depths[i], '-') minspeed = np.amin(self.sspeed) maxspeed = np.amax(self.sspeed) ax.set_xlim([ np.amin(self.sspeed) - (maxspeed - minspeed) * 0.1, np.amax(self.sspeed) + (maxspeed - minspeed) * 0.1, ]) ax.set_xlabel(gettext("Sound Speed (m/s)"), fontsize=14) ax.set_ylabel(gettext("Depth (m)"), fontsize=14) ax.invert_yaxis() ax.xaxis.set_ticks_position('top') ax.xaxis.set_label_position('top') x_format = tkr.FuncFormatter(lambda x, pos: "%d" % x) ax.xaxis.set_major_formatter(x_format) if self.plotTitle is None or self.plotTitle == "": ax.set_title( gettext("Sound Speed Profile for (%s)\n%s") % (", ".join(self.names), self.date_formatter(self.timestamp)), fontsize=15) else: ax.set_title(self.plotTitle, fontsize=15) ax.title.set_position([.5, 1.10]) plt.subplots_adjust(top=0.85) ax.xaxis.grid(True) self.plot_legend(fig, self.names) ylim = ax.get_ylim() ax2 = ax.twinx() ureg = pint.UnitRegistry() ax2.set_ylim((ylim * ureg.meters).to(ureg.feet).magnitude) ax2.set_ylabel(gettext("Depth (ft)"), fontsize=14) return super(plTS.TemperatureSalinityPlotter, self).plot(fig)