def plot_cross_sections(tracers, pv, theta, theta_e, rh, z_bl, fig, ylims): # Plot each cube separately for n, cube in enumerate(tracers): row = n / ncols col = n - row * ncols ax = plt.subplot2grid((nrows, ncols), (row, col)) # Interpolate along the cross section im = plot_cross_section(cube, pv, theta, theta_e, z_bl, rh, ax, n, ylims) # Add letter labels to panels for n, ax in enumerate(fig.axes): multilabel(ax, n) # Add colorbar at bottom of figure cbar = plt.colorbar(im, ax=fig.axes, orientation='horizontal', fraction=0.05, spacing='proportional') cbar.set_label('K') cbar.set_ticks(np.linspace(-20, 20, 9)) fig.text(0.075, 0.58, 'Height (km)', va='center', rotation='vertical') fig.text(0.5, 0.2, 'Grid Longitude', ha='center') return
def main(cubes, levels, *args, **kwargs): # Initialise the plot fig = plt.figure(figsize=(18, 20)) for n, name in enumerate(names): row = n / ncols col = n - row * ncols print(row, col) ax = plt.subplot2grid((nrows, ncols), (row, col)) cube = convert.calc(name, cubes, levels=levels)[0] im = iplt.pcolormesh(cube, *args, **kwargs) add_map() plt.title(second_analysis.all_diagnostics[name].symbol, fontsize=30) for n, ax in enumerate(fig.axes): multilabel(ax, n, fontsize=25) cbar = plt.colorbar(im, ax=fig.axes, orientation='horizontal', fraction=0.05, spacing='proportional') cbar.set_label('PVU') # cbar.set_ticks(np.array(levels)[::2]) plt.savefig(plotdir + '../../iop8_bl_map.png') # plt.show() return
def bottom_level(tracers, mslp, fig, **kwargs): # Plot each cube separately for n, cube in enumerate(tracers): row = n / ncols col = n - row * ncols ax = plt.subplot2grid((nrows, ncols), (row, col)) # Make the plot im = iplt.pcolormesh(cube[0], **kwargs) mslp.convert_units('hPa') cs = iplt.contour(mslp, plevs, colors='k', linewidths=2) plt.clabel(cs, fmt='%1.0f') add_map() plt.title(second_analysis.all_diagnostics[cube.name()].symbol) # Label the cross section points if n == 0: plt.plot([xs, xf], [ys, yf], '-kx') plt.text(xs, ys, 'A', fontsize=20) plt.text(xf, yf, 'B', fontsize=20) # Add letter labels to panels for n, ax in enumerate(fig.axes): multilabel(ax, n) # Add colorbar at bottom of figure cbar = plt.colorbar(im, ax=fig.axes, orientation='horizontal', fraction=0.05) cbar.set_label('PVU') return
def main(cubes): theta = convert.calc('equivalent_potential_temperature', cubes) P = convert.calc('air_pressure', cubes) P.convert_units('hPa') mass = convert.calc('mass', cubes) lon, lat = grid.true_coords(theta) lonmask = np.logical_or(lon < -15, lon > 5) latmask = np.logical_or(lat < 47.5, lat > 62.5) areamask = np.logical_or(lonmask, latmask) masks = [ np.logical_or(theta.data < theta_front, areamask), np.logical_or(theta.data > theta_front, areamask) ] #overview(cubes, areamask) #plt.savefig(plotdir + 'composite_iop8_24h_overview_750hpa.pdf') # plt.show() z_cold, z_warm = bl_heights(cubes, theta, areamask) # Initialise the plot fig = plt.figure(figsize=(18, 12)) diags = convert.calc(names, cubes) masses = [] # Rows are different masks for n, mask in enumerate(masks): means = diagnostics.averaged_over(diags, levels, P, mass, mask) masses.append(convert.calc('mass', means)) # Columns are for different mappings for m, mapping in enumerate(mappings): ax = plt.subplot2grid((2, ncol), (n, m)) composite(means, ax, mapping, mass, P) add_trimmings(ax, n, m) if m == 0: ax.set_xlim(0.1, 1.3) elif m == 1: ax.set_xlim(-0.6, 0.6) else: ax.set_xlim(-1, 1) multilabel(ax, 3 * n + m, yreversed=True, fontsize=25) if n == 0: plt.axhline(z_cold, color='k', linestyle='--') elif n == 1: plt.axhline(z_warm, color='k', linestyle='--') add_figlabels(fig) fig.savefig(plotdir + 'composite_iop5_24h.pdf') plt.figure() for mass in masses: qplt.plot(mass, mass.coord('air_pressure')) ax.set_ylim(950, 500) plt.show() return
def main(cubes): """Plot contours of theta on PV2 coloured by whether they are ridges or troughs """ # Initialise the figure fig = plt.figure(figsize=(18, 15)) # Background state eqlats vs theta ax = plt.subplot2grid((2, 2), (0, 0)) background_eqlats() multilabel(ax, 0) # Background state theta vs latitude vs time ax = plt.subplot2grid((2, 2), (0, 1)) background_theta() multilabel(ax, 1) # Forecast theta on tropopause ax = plt.subplot2grid((2, 2), (1, 0)) theta, lon, lat = forecast_theta(cubes) #multilabel(ax, 2) # Anomaly of theta on tropopause ax = plt.subplot2grid((2, 2), (1, 1)) theta_anomaly(theta, lon, lat) #multilabel(ax, 3) plt.savefig(plotdir + 'ridges_troughs.pdf') plt.show() return
def profile(coord, mappings, domains, title, xlabel, ylabel, xlims, ylims): ncols = len(mappings) nrows = len(domains) # Initialise the plot fig = plt.figure(figsize=(18, 25)) # Loop over mappings for m, domain in enumerate(domains): cubes = second_analysis.get_data(coord, domain) for n, mapping in enumerate(mappings): mapping = second_analysis.mappings[mapping] ax = plt.subplot2grid((nrows, ncols), (m, n)) profile_multi(cubes, ax, mapping, coord) ax.set_xlim(*xlims[n]) ax.set_ylim(*ylims) if m == 0: ax.set_title(title[n]) else: ax.set_title('') if m == nrows - 1: legend(ax, key=second_analysis.get_idx, loc='upper left', ncol=2, bbox_to_anchor=(0.05, -0.25)) else: ax.get_xaxis().set_ticklabels([]) if n == 0: if m == 1: ax.set_ylabel(ylabel) else: ax.set_ylabel('') else: ax.set_ylabel('') ax.get_yaxis().set_ticklabels([]) if m == nrows - 1 and n == 1: ax.set_xlabel(xlabel) else: ax.set_xlabel('') ax.axvline(color='k') ax.axhline(color='k') if coord == 'air_pressure': ax.set_ylim(ax.get_ylim()[::-1]) multilabel(ax, n + m * ncols) fig.subplots_adjust(bottom=0.4) return
def tropopause_profile(): # Initialise the plot fig = plt.figure(figsize=(18, 15)) # Loop over mappings for n, mapping in enumerate(mappings): mapping = second_analysis.mappings[mapping] for m, domain in enumerate(['ridges', 'troughs']): cubes = second_analysis.get_data(coord, domain) ax = plt.subplot2grid((2, ncols), (m, n)) if n == 0: profile_error(cubes, ax, mapping, coord) else: profile_multi(cubes, ax, mapping, coord) plt.title(title[n]) ax.set_xlim(*xlims[n]) ax.set_ylim(*ylim) legend(ax, key=second_analysis.get_idx, loc='best', ncol=2, bbox_to_anchor=(0.9, -0.2)) if n == 0: ax.set_ylabel(ylabel) else: ax.set_ylabel('') ax.get_yaxis().set_ticklabels([]) if n == 1: ax.set_xlabel(xlabel) else: ax.set_xlabel('') plt.title('') plt.axvline(color='k') plt.axhline(color='k') # if coord == 'air_pressure': # ax.set_ylim(ax.get_ylim()[::-1]) for n, ax in enumerate(fig.axes): multilabel(ax, n) fig.subplots_adjust(bottom=0.4) #plt.savefig(plotdir + 'ch7_low/height_profile.pdf') plt.show() return
def cross_sections(tracers, theta, rh, z_bl, fig): # Plot each cube separately for n, cube in enumerate(tracers): row = n / ncols col = n - row * ncols ax = plt.subplot2grid((nrows, ncols), (row, col)) # Interpolate along the cross section cube = cs_cube(cube, xs, xf, ys, yf) coords = ['grid_longitude', 'altitude'] # Make the plot im = iplt.contourf(cube, even_cscale(2), coords=coords, cmap='coolwarm', extend='both') cs = iplt.contour(theta, theta_levs, coords=coords, colors='k', linewidths=2) iplt.plot(z_bl.coord('grid_longitude'), z_bl, color='y') iplt.contour(rh, [0.8], coords=coords, colors='w') iplt.contourf(rh, [0.8, 2], coords=coords, colors='None', hatches=['.']) plt.title(second_analysis.all_diagnostics[cube.name()].symbol) if n == 0: plt.clabel(cs, fmt='%1.0f', colors='k') ax.set_ylim(0, 7) if n < 4: ax.set_xticks([]) # Add letter labels to panels for n, ax in enumerate(fig.axes): multilabel(ax, n) # Add colorbar at bottom of figure cbar = plt.colorbar(im, ax=fig.axes, orientation='horizontal', fraction=0.05, spacing='proportional') cbar.set_label('PVU') cbar.set_ticks(np.linspace(-2, 2, 9)) fig.text(0.075, 0.58, 'Height (km)', va='center', rotation='vertical') fig.text(0.5, 0.2, 'Grid Longitude', ha='center') return
def main(): forecast = case_studies.iop8_no_microphysics.copy() cubes = forecast.set_lead_time(hours=18) names = [ 'ertel_potential_vorticity', 'total_minus_advection_only_pv', 'long_wave_radiation_pv', 'microphysics_pv', 'convection_pv', 'boundary_layer_pv', ] nrows = int(floor(np.sqrt(len(names)))) ncols = int(ceil(len(names) / float(nrows))) mask = make_mask(cubes) mass = convert.calc('mass', cubes) fig = plt.figure(figsize=(18, 10)) for n, name in enumerate(names): row = n / ncols col = n - row * ncols plt.subplot2grid((nrows, ncols), (row, col)) im = make_plot(cubes, name, mass, mask, vmin=-2, vmax=2, cmap='coolwarm') plt.title(all_diagnostics[name].symbol) # Add letter labels to panels for n, ax in enumerate(fig.axes): multilabel(ax, n) # Add colorbar at bottom of figure cbar = plt.colorbar(im, ax=fig.axes, orientation='horizontal', fraction=0.05, spacing='proportional') cbar.set_label('PVU') cbar.set_ticks(np.linspace(-2, 2, 9)) plt.savefig(plotdir + 'iop8_no_microphysics_bl_depth_average_pv.png') plt.show() return
def main(): forecasts = [case_studies.iop5b.copy(), case_studies.iop8.copy()] fig = plt.figure(figsize=(18, 8)) for n, forecast in enumerate(forecasts): ax = plt.subplot2grid((1, 2), (0, n)) cubes = forecast.set_lead_time(hours=24) theta = convert.calc('air_potential_temperature', cubes) bl_type = convert.calc('boundary_layer_type', cubes) for m in range(4): mask = np.logical_not( np.logical_or(bl_type.data == 2 * m, bl_type.data == 2 * m + 1)) mask = mask * np.ones_like(theta.data) mean = theta_profile(theta, mask) mean = mean - mean[0] iplt.plot(mean, mean.coord('atmosphere_hybrid_height_coordinate'), style[m], label=label[m]) #mask = np.logical_not(mask) #mean = theta_profile(theta, mask) # iplt.plot(mean, mean.coord('atmosphere_hybrid_height_coordinate'), # '-kx') ax.set_xlim(-0.25, 4.5) ax.set_xlabel(r'$\theta$') ax.set_ylim(0, 1000) if n == 0: ax.set_ylabel('Height (m)') ax.set_title('IOP5') else: ax.get_yaxis().set_ticklabels([]) ax.set_title('IOP8') plt.axvline(color='k') multilabel(ax, n) legend(ax, loc='upper left', ncol=2, bbox_to_anchor=(-0.6, -0.2)) fig.subplots_adjust(bottom=0.4) fig.savefig(plotdir + 'theta_profiles.pdf') plt.show() return
def main(**kwargs): # Initialise the plot fig = plt.figure(figsize=(18, 15)) for n, coord in enumerate(coords): for m, subdomain in enumerate(['ridges', 'troughs']): cubes = second_analysis.get_data(coord, subdomain) cube = convert.calc(name, cubes) cube.coord(coord).convert_units('km') mean, std_err = second_analysis.extract_statistics( cube, 'forecast_index') ax = plt.subplot2grid((2, 2), (n, m)) im = iplt.contourf(mean, even_cscale(0.18), cmap='coolwarm') # X-axis - Same for both columns ax.set_xticks([0, 12, 24, 36, 48, 60]) if n == 0: ax.get_xaxis().set_ticklabels([]) ax.set_title(subdomain.capitalize()) # Y-axis - Same for both rows ax.set_ylim(-2, 2) ax.set_yticks([-2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2]) ax.axhline(color='k') if m > 0: ax.get_yaxis().set_ticklabels([]) add_labels(fig) fig.text(0.5, 0.2, 'Forecast Lead Time (hours)', ha='center') for n, axis in enumerate(fig.axes): multilabel(axis, n) cbar = plt.colorbar(im, ax=fig.axes, orientation='horizontal', fraction=0.05, spacing='proportional') cbar.set_ticks([-0.18, -0.09, 0, 0.09, 0.18]) cbar.set_label('PVU') plt.savefig(plotdir + 'inconsistency.pdf') plt.show() return
def main(cubes, levels, *args, **kwargs): # Initialise the plot fig = plt.figure(figsize=(18, 20)) pv = convert.calc('ertel_potential_vorticity', cubes, levels=levels)[0] theta = convert.calc('equivalent_potential_temperature', cubes, levels=levels)[0][slices] rh = convert.calc('relative_humidity', cubes, levels=levels)[0][slices] lon, lat = grid.true_coords(theta) lonmask = np.logical_or(lon < -15, lon > 5) latmask = np.logical_or(lat < 47.5, lat > 62.5) areamask = np.logical_or(lonmask, latmask) mask = theta.copy(data=areamask.astype(int)) for n, name in enumerate(names): row = n / ncols col = n - row * ncols print(row, col) ax = plt.subplot2grid((nrows, ncols), (row, col)) cube = convert.calc(name, cubes, levels=levels)[0] # [slices] im = iplt.contourf(cube, *args, **kwargs) #iplt.contour(pv, [2], colors='k', linewidths=2) iplt.contour(mask, [0.5], colors='k', linestyles='--') add_map() plt.title(second_analysis.all_diagnostics[name].symbol) iplt.contour(theta, [300], colors='k', linewidths=2) iplt.contour(rh, [0.8], colors='w', linewidths=2) iplt.contourf(rh, [0.8, 2], colors='None', hatches=['.']) for n, ax in enumerate(fig.axes): multilabel(ax, n) cbar = plt.colorbar(im, ax=fig.axes, orientation='horizontal', fraction=0.05, spacing='proportional') cbar.set_label('PVU') cbar.set_ticks(np.linspace(-2, 2, 17)[::2]) plt.savefig(plotdir + 'iop5_pv_tracers_24h_' + str(levels[1][0])[0:3] + 'hpa.pdf') # plt.show() return
def make_plot_pair(filename, time_cs, precision_cs, axes, factor): cubes = iris.load(filename) for cube in cubes: cube.coord('forecast_period').convert_units('days') plt.axes(axes[0]) multilabel(axes[0], 0, factor=factor) make_plot(cubes, precision_cs) legend(key=lambda x: physics_schemes[x[0]].idx, ncol=2, title='Parametrization Schemes') plt.xlabel('Forecast Lead Time [days]') plt.ylabel('RMS Error in Geopotential Height [m]') plt.axes(axes[1]) multilabel(axes[1], 1, factor=factor) make_plot(cubes, time_cs) plt.xlabel('Precision [sbits]') return
def bl_categories(): # Initialise the plot fig = plt.figure(figsize=(18, 10)) for n, forecast in enumerate(forecasts): cubes = forecast.set_lead_time(hours=24) ax = plt.subplot2grid((1, 2), (0, n)) if n == 0: plt.title('IOP5') elif n == 1: plt.title('IOP8') multilabel(ax, n + 2) bl_type = convert.calc('boundary_layer_type', cubes) cmap = mpl.colors.ListedColormap([t[1] for t in types]) iplt.pcolormesh(bl_type, cmap=cmap) overlay_pressure(cubes) add_map() # Add category map legend handles = [] for bl_type, colour in types: handles.append(mpatches.Patch(color=colour, label=bl_type)) ax = fig.axes[1] ax.legend(handles=handles, ncol=2, loc='upper_right', bbox_to_anchor=(0.95, -0.1)) fig.subplots_adjust(bottom=0.5) plt.savefig(plotdir + 'bl_categories') return
def bl_heights(**kwargs): # Initialise the plot fig = plt.figure(figsize=(18, 10)) for n, forecast in enumerate(forecasts): cubes = forecast.set_lead_time(hours=24) ax = plt.subplot2grid((1, 2), (0, n)) z_bl = convert.calc('atmosphere_boundary_layer_thickness', cubes) z_bl.convert_units('km') im = iplt.pcolormesh(z_bl, **kwargs) cs = overlay_pressure(cubes) plt.clabel(cs, fmt='%1.0f') add_map() if n == 0: plt.title('IOP5') elif n == 1: plt.title('IOP8') multilabel(ax, n) # Add BL Height colourscale cbar = plt.colorbar(im, ax=fig.axes, fraction=0.05, orientation='horizontal', extend='max') cbar.set_label('Boundary layer thickness (km)') cbar.set_ticks(np.linspace(0, 3, 7)) plt.savefig(plotdir + 'bl_heights') return
def main2(variable, sigma, table): # Create a two by two grid fig, axes = plt.subplots(nrows=1, ncols=2, sharey='row', figsize=(16, 5), subplot_kw={'yscale': 'log'}) # Show the reference machine epsilon sbits = np.arange(5, 24) machine_error = 2.0**-(sbits + 1) # Errors with respect to individual parametrization tendency plt.axes(axes[0]) for scheme in schemes: plp = speedy.physics_schemes[scheme] try: fp = load_tendency(variable=variable, scheme=scheme, rp_scheme='all_parametrizations', sigma=sigma, precision=52) rp = load_tendency(variable=variable, scheme=scheme, rp_scheme=filename(scheme), sigma=sigma, precision=sbits) # Ignore where tendencies are zero rp.data = np.ma.masked_where((rp.data - fp.data) == 0, rp.data) display_errors(rp, fp, plp) except iris.exceptions.ConstraintMismatchError: print('{} cannot be loaded \n'.format(scheme)) # Errors with respect to total parametrization tendency plt.axes(axes[1]) fp = load_tendency(variable=variable, rp_scheme='all_parametrizations', sigma=sigma, precision=52) tendency = global_mean(maths.abs(fp)) tendency = collapse_sigma(tendency) axes[1].axhline(tendency.data, linestyle='--', color='k', alpha=0.5) axes[1].plot(sbits, machine_error * tendency.data, ':k', alpha=0.5) for scheme in schemes: plp = speedy.physics_schemes[scheme] rp = load_tendency(variable=variable, rp_scheme=filename(scheme), sigma=sigma, precision=sbits) error = display_errors(rp, fp, plp, label=scheme) error = (error / tendency) / machine_error table[scheme] += ' & ${:.0f}-{:.0f}\\varepsilon$'.format( error.data.min(), error.data.max()) # Add dressing to the plot multilabel(axes[0], 0, factor=0.01) axes[0].set_title('Individual Temperature Tendency') axes[0].set_ylabel('Average Tendency Error [{}]'.format(tendency.units)) axes[0].set_xticks(sbits[::5]) multilabel(axes[1], 1, factor=0.01) axes[1].set_title('Total Temperature Tendency') axes[1].set_xticks(sbits[::5]) fig.text(0.45, 0.01, 'Precision [sbits]') legend(ax=axes[1], key=lambda x: speedy.physics_schemes[x[0]].idx, ncol=2) plt.subplots_adjust(left=0.08, right=0.98, wspace=0.05) return
def humidity_gradients(): # Initialise the plot fig = plt.figure(figsize=(18, 15)) # Columns are Ridges and troughs for n, variable in enumerate(variables): row = n / ncols col = n - row * ncols print(row, col) ax = plt.subplot2grid((nrows, ncols), (row, col)) for subdomain, linestyle in [('ridges', '-'), ('troughs', '--')]: cubes = second_analysis.get_data(coord, subdomain) cube = convert.calc(variable, cubes) cube.coord(coord).convert_units('km') mean, std_err = second_analysis.extract_statistics( cube, 'forecast_index') if variable == 'vertical_vorticity': mean.data = mean.data + 1e-4 else: mean.data = mean.data * 1e3 std_err.data = std_err.data * 1e3 iplt.plot( mean[0], mean.coord(coord), # xerr=std_err[0], linestyle=linestyle, label=subdomain.capitalize(), color='k', marker='x', ms=5) ax.set_ylabel('') ax.set_ylim(-2, 2) if col > 0: ax.get_yaxis().set_ticklabels([]) if variable == 'specific_humidity': ax.set_title('Specific Humidity') ax.set_xlabel(r'Mass Fraction (g kg$^{-1}$)') elif variable == 'vertical_vorticity': ax.set_title('Vertical Vorticity') ax.set_xlabel(r'Vorticity (s$^{-1}$)') elif variable == 'mass_fraction_of_cloud_liquid_water_in_air': ax.set_title('Cloud Liquid') ax.set_xlabel(r'Mass Fraction (g kg$^{-1}$)') elif variable == 'mass_fraction_of_cloud_ice_in_air': ax.set_title('Cloud Ice') ax.set_xlabel(r'Mass Fraction (g kg$^{-1}$)') plt.axhline(color='k') multilabel(ax, n) legend(ax=fig.axes[0], loc='best') fig.text(0.075, 0.5, 'Vertical distance from tropopause (km)', va='center', rotation='vertical') plt.savefig(plotdir + 'analysis_profiles.pdf') plt.show()
def main(): # Specify which files and variable to compare path = datadir filename = 'precision_errors_geopotential_height_200hpa.nc' factor = 0.01 # Set colour, linestyle and marker for each individual line cm = plt.cm.tab10 # Plots vs precision precisions = [ ( 10, colourblind.blue, '-', 'o', ), ( 23, colourblind.green, '-', 'o', ), ( 51, colourblind.orange, '-', 'o', ), ( 11, colourblind.pink, '--', 'o', ), ( 22, colourblind.yellow, '--', 'o', ), ( 35, colourblind.purple, '--', 'o', ), ] # Plots vs lead time lead_times = [(7, 'k', '-', ''), (14, colourblind.blue, '--', ''), (21, colourblind.green, '-', ''), (28, colourblind.orange, '--', '')] # Load the cube with the rms errors cs = iris.Constraint( name= 'RMS error in Geopotential Height with All Parametrizations in reduced precision' ) cube = iris.load_cube(path + filename, cs) cube.coord('forecast_period').convert_units('days') # Create a two by two grid with shared x and y axes along rows and columns fig, axes = plt.subplots(nrows=2, ncols=2, sharex='col', sharey='row', figsize=[16, 9]) # Normal yscale and log scale for n in range(2): # Error vs time plt.axes(axes[n, 0]) multilabel(axes[n, 0], 2 * n, factor=factor) make_plot(cube, precisions, 'precision') if n == 0: plt.legend(title='Precision [sbits]', ncol=2) elif n == 1: plt.xlabel('Forecast Lead Time [days]') # Error vs precision plt.axes(axes[n, 1]) multilabel(axes[n, 1], 2 * n + 1, factor=factor) make_plot(cube, lead_times, 'forecast_period') if n == 0: plt.legend(title='Lead Time [days]', ncol=2) elif n == 1: plt.xlabel('Precision [sbits]') # Put the second row of plots on a log scale plt.yscale('log') fig.text(0.05, 0.5, 'RMS Error in Geopotential Height [m]', va='center', rotation='vertical') plt.show() return
def varying_depth(widths, function): fig = plt.figure(figsize=(18, 8)) axes = [] for n in range(1): for m in range(2): axes.append(plt.subplot2grid((1, 2), (n, m))) for coord, color in coords: for subdomain, linestyle in subdomains: cubes = second_analysis.get_data(coord, subdomain) pv = convert.calc(variable, cubes) if subdomain == 'ridges': x, y, dy = pv_contrast(pv, coord, 1000) popt, pcov, rmse = fit_curve(x, y, dy) axes[0].errorbar(x, y, yerr=dy, linestyle=linestyle, color=color) pv = pv[:, 1:] if subdomain == 'ridges': x2, y, dy = pv_contrast(pv, coord, 1000) popt, pcov, rmse = fit_curve(x2, y, dy) axes[0].plot(x, func(x, *popt), color=color, linestyle='', marker='o') timescale = [] grad_0 = [] grad_inf = [] errors = [] for dz in widths: if dz == 200: x, y, dy = pv_gradient(pv, coord, dz) else: x, y, dy = function(pv, coord, dz) popt, pcov, rmse = fit_curve(x, y, dy) timescale.append(popt[0]) grad_0.append(popt[1]) grad_inf.append(popt[2]) errors.append(rmse) grad_0 = np.array(grad_0) grad_inf = np.array(grad_inf) # axes[2].plot(widths * 1e-3, grad_0, # color=color, linestyle=linestyle, marker='x') # axes[3].plot(widths * 1e-3, grad_0 - grad_inf, # color=color, linestyle=linestyle, marker='x') axes[1].plot(widths * 1e-3, timescale, color=color, linestyle=linestyle, marker='x') # axes[5].plot(widths * 1e-3, errors, # color=color, linestyle=linestyle, marker='x') # Set figure labels axes[0].set_title(r'$\Delta q_{adv}(t)$ in ridges') axes[0].set_xlabel('Forecast Lead Time (hours)') axes[0].set_ylabel('PVU') axes[1].set_title('Timescale') axes[1].set_xlabel(r'$\pm \tilde{z}$ (km)', fontsize=20) axes[1].set_ylabel(r'$\tau$ (Hours)') """ axes[2].set_title(r'$\Delta q_{adv}(0)$') axes[2].set_xlabel(r'$\pm \tilde{z}$ (km)', fontsize=20) axes[2].set_ylabel('PVU') #axes[2].set_ylim(0, 5) axes[3].set_title(r'$\Delta q_{adv}(0) - \Delta q_{adv}(\infty)$') axes[3].set_xlabel(r'$\pm \tilde{z}$ (km)', fontsize=20) axes[3].set_ylabel('PVU') #axes[3].set_ylim(0, 5) """ for n, axis in enumerate(axes): multilabel(axis, n) # Create legend table fig2 = plt.figure() ax = fig2.add_subplot(111) lines = [] for subdomain, linestyle in subdomains: for coord, color in coords: lines.append( ax.plot([0, 1], [0, 1], linestyle=linestyle, color=color)[0]) # create blank rectangle extra = Rectangle((0, 0), 1, 1, fc="w", fill=False, edgecolor='none', linewidth=0) # Create organized list containing all handles for table. Extra represent # empty space legend_handle = [ extra, extra, extra, extra, lines[0], lines[1], extra, lines[2], lines[3] ] # Define the labels label_column_1 = ["", r"$z(q{=}2)$", r"$z(q_{adv}{=}2)$"] label_column_2 = ["Ridges", "", ""] label_column_3 = ["Troughs", "", ""] # organize labels for table construction legend_labels = np.concatenate( [label_column_1, label_column_2, label_column_3]) # Create legend axes[1].legend(legend_handle, legend_labels, loc='best', ncol=3, shadow=True, handletextpad=-2) fig.savefig(plotdir + 'q_adv_decay_parameters.pdf') # plt.show() return
def main(): # Initialise the plot fig = plt.figure(figsize=(18, 12)) # Add subfigures for n in range(2): for m in range(3): plt.subplot2grid((2, 3), (n, m)) # Plot composites pv_gradients('distance_from_dynamical_tropopause', 1, fig) # Add faint lines for q_adv #pv_gradients('distance_from_advection_only_tropopause', 0.25, fig) for n, subdomain in enumerate(['ridges', 'troughs']): coord = 'distance_from_advection_only_tropopause' alpha = 0.3 cubes = second_analysis.get_data(coord, subdomain) m = 1 mapping = second_analysis.mappings['pv_main'] mapping = { k: mapping[k] for k in ('dynamics_tracer_inconsistency', 'sum_of_physics_pv_tracers') } ax = fig.axes[n * 3 + m] pv_gradients_multi(cubes, coord, ax, mapping, alpha) fig.subplots_adjust(bottom=0.2) # Set labels and limits on plots for n, subdomain in enumerate(['ridges', 'troughs']): for m in range(3): ax = fig.axes[n * 3 + m] # X-axis - Same for both rows ax.set_xticks([0, 12, 24, 36, 48, 60]) if n == 0: ax.get_xaxis().set_ticklabels([]) # Set Titles if m == 0: ax.set_title('Forecast') elif m == 1: ax.set_title('PV budget') elif m == 2: ax.set_title('Physics PV tracers') else: legend(ax, key=second_analysis.get_idx, loc='best', ncol=2, bbox_to_anchor=(1.0, -0.2), fontsize=25) if m == 1: ax.set_xlabel('Forecast lead time (hours)') # Y-Axis if m == 0: # First column custom if n == 0: ax.set_ylim(3.0, 3.6) else: ax.set_ylim(2.4, 3.0) elif m == 1: # Columns 2 ax.set_ylim(-0.1, 0.5) else: ax.set_ylim(-0.05, 0.25) multilabel(ax, n * 3 + m) fig.text(0.075, 0.55, 'PV (PVU)', va='center', rotation='vertical', fontsize=20) fig.text(0.05, 0.75, 'Ridges', va='center', rotation='vertical', fontsize=20) fig.text(0.05, 0.35, 'Troughs', va='center', rotation='vertical', fontsize=20) plt.savefig(plotdir + 'pv_gradients_new.pdf') plt.show() return
def main(): path = datadir + 'stochastic/ensembles/' # Get overlap from exchanged ensembles ovl_range = iris.load(path + 'ovl_perturbed_??.nc') for n, cube in enumerate(ovl_range): cube.add_aux_coord(iris.coords.AuxCoord(n, long_name='ensemble')) ovl_range = ovl_range.merge_cube() ovl_range.coord('forecast_period').convert_units('days') ovl_min = ovl_range.collapsed('ensemble', MIN) ovl_max = ovl_range.collapsed('ensemble', MAX) ovl_mean = ovl_range.collapsed('ensemble', MEAN) # Two panels fig, axes = plt.subplots(nrows=1, ncols=2, sharey='row', figsize=[16, 5]) # Panel 1 - plt.axes(axes[0]) multilabel(axes[0], 0, 0.01) plt.fill_between(ovl_range.coord('forecast_period').points, ovl_min.data, ovl_max.data, color='grey') files = [ ('overlap_52_23.nc', '23 sbit', '-', 'k'), ('overlap_52_10.nc', '10 sbit', '--', 'k'), ('overlap_52_8.nc', '8 sbit', ':', 'k'), ('overlap_52_adj8.nc', '8 sbit, Fixed', '--', 'y'), ('overlap_52_half_precision_exponent.nc', '10 sbit, Exponent', '-', 'y') ] for filename, label, linestyle, color in files: overlap = iris.load_cube(path + filename) overlap.coord('forecast_period').convert_units('days') iplt.plot(overlap, label=label, color=color, linestyle=linestyle) legend() # Panel 2 plt.axes(axes[1]) multilabel(axes[1], 1, 0.01) plt.fill_between(ovl_range.coord('forecast_period').points, ovl_min.data, ovl_max.data, color='grey') files = [ ('overlap_52_cnv8.nc', 'Convection'), ('overlap_52_cond8.nc', 'Condensation'), ('overlap_52_swrad8.nc', 'Short-Wave Radiation'), ('overlap_52_lwrad8.nc', 'Long-Wave Radiation'), ('overlap_52_sflx8.nc', 'Surface Fluxes'), ('overlap_52_vdif8.nc', 'Vertical Diffusion'), ] for filename, label in files: overlap = iris.load_cube(path + filename) overlap.coord('forecast_period').convert_units('days') plp = physics_schemes[label] plp.plot(overlap, label=label) legend() plt.ylabel('Overlapping Coefficient') fig.text(0.5, 0.01, 'Forecast Lead Time [days]', ha='center') plt.show() return
def main(cubes, **kwargs): # Pre-calculate parameters on every plot mslp = convert.calc('air_pressure_at_sea_level', cubes) mslp.convert_units('hPa') theta = convert.calc('equivalent_potential_temperature', cubes, levels=levels)[0] rh = convert.calc('relative_humidity', cubes) fig = plt.figure(figsize=(18, 15)) lon, lat = grid.true_coords(theta) lonmask = np.logical_or(lon < -15, lon > 5) latmask = np.logical_or(lat < 47.5, lat > 62.5) areamask = np.logical_or(lonmask, latmask) # Plot overview ax1 = plt.subplot2grid((2, 2), (0, 0)) iplt.contourf(theta, theta_levs, cmap='coolwarm', extend='both') add_map() cs = iplt.contour(mslp, plevs, colors='k', linewidths=2) plt.clabel(cs, fmt='%1.0f') mask = theta.copy(data=areamask.astype(int)) iplt.contour(mask, [0.5], colors='k', linestyles='--') count = 0 for n, (xs, xf, ys, yf) in enumerate(points, start=1): # Label the cross section points plt.plot([xs, xf], [ys, yf], '-kx') plt.text(xs, ys, ascii_uppercase[count], color='k', fontsize=20) count += 1 plt.text(xf, yf, ascii_uppercase[count], color='k', fontsize=20) count += 1 multilabel(plt.gca(), 0) theta = convert.calc('equivalent_potential_temperature', cubes) # Plot cross sections titles = ['AB', 'CD', 'EF'] coords = ['grid_longitude', 'altitude'] for n, (xs, xf, ys, yf) in enumerate(points, start=1): row = n / ncols col = n - row * ncols ax = plt.subplot2grid((nrows, ncols), (row, col)) theta_cs = cs_cube(theta, xs, xf, ys, yf) rh_cs = cs_cube(rh, xs, xf, ys, yf) im = iplt.contourf(theta_cs, theta_levs, coords=coords, cmap='coolwarm', extend='both') iplt.contour(rh_cs, rh_levs, coords=coords, colors='w') iplt.contourf(rh_cs, [0.8, 2], coords=coords, colors='None', hatches=['.']) ax.set_ylim(0, 7) if xs > xf: ax.invert_xaxis() multilabel(ax, n, xreversed=True) else: multilabel(ax, n) ax.set_title(titles[n - 1]) ax.set_ylabel('Height (km)') ax.set_xlabel('Grid Longitude') # Add colorbar at bottom of figure cbar = plt.colorbar(im, ax=fig.axes, orientation='horizontal', fraction=0.05, spacing='proportional') cbar.set_label('PVU') fig.savefig(filename) plt.show()
def main(): # Initialise the plot fig = plt.figure(figsize=(18, 12)) # Add subfigures for n in range(2): for m in range(3): plt.subplot2grid((2, 3), (n, m)) # Plot composites tropopause_profile('distance_from_dynamical_tropopause', 1, fig) # Add faint lines for q_adv #tropopause_profile('distance_from_advection_only_tropopause', 0.25, fig) for n, subdomain in enumerate(['ridges', 'troughs']): coord = 'distance_from_advection_only_tropopause' alpha = 0.3 cubes = second_analysis.get_data(coord, subdomain) m = 1 mapping = second_analysis.mappings['pv_main'] mapping = { k: mapping[k] for k in ('dynamics_tracer_inconsistency', 'sum_of_physics_pv_tracers') } ax = fig.axes[n * 3 + m] profile_multi(cubes, coord, ax, mapping, alpha) fig.subplots_adjust(bottom=0.2) # Set labels and limits on plots for n, subdomain in enumerate(['ridges', 'troughs']): for m in range(3): ax = fig.axes[n * 3 + m] # X-axis - Same for all plots if m == 0: ax.set_xlim(-0.5, 0.2) ax.set_xticks([-0.4, -0.2, 0, 0.2]) else: ax.set_xlim(-0.2, 0.3) ax.set_xticks([-0.2, -0.1, 0, 0.1, 0.2, 0.3]) if n == 0: ax.get_xaxis().set_ticklabels([]) # Set Titles if m == 0: ax.set_title('Forecast minus analysis') elif m == 1: ax.set_title('PV budget') elif m == 2: ax.set_title('Physics PV tracers') else: legend(ax, key=second_analysis.get_idx, loc='best', ncol=2, bbox_to_anchor=(1.0, -0.2), fontsize=25) if m == 1: ax.set_xlabel('PV (PVU)') # Y-axis - Same for all plots ax.set_ylim(-2, 2) ax.set_yticks([-2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2]) if m != 0: ax.get_yaxis().set_ticklabels([]) multilabel(ax, n * 3 + m) fig.text(0.075, 0.55, 'Vertical distance from tropopause (km)', va='center', rotation='vertical', fontsize=20) fig.text(0.05, 0.75, 'Ridges', va='center', rotation='vertical', fontsize=20) fig.text(0.05, 0.35, 'Troughs', va='center', rotation='vertical', fontsize=20) plt.savefig(plotdir + 'tropopause_profile_new.pdf') # plt.show() return