def main(cubes): # Load the data res = convert.calc('residual_pv', cubes) pv = convert.calc('ertel_potential_vorticity', cubes) expected_pv = pv - res stats = [] # Calculation correlation on each model level for n in range(pv.shape[0]): stats.append( linregress(pv[n].data.flatten(), expected_pv[n].data.flatten())) stats = np.array(stats) print(stats.shape) fig = plt.figure(figsize=(18, 20)) ax = plt.subplot2grid((2, 2), (0, 0)) plt.plot(stats[:, 2]) plt.title('Correlation Coefficient') ax = plt.subplot2grid((2, 2), (1, 0)) plt.plot(stats[:, 0]) plt.title('Gradient') ax = plt.subplot2grid((2, 2), (1, 1)) plt.plot(stats[:, 1]) plt.title('Intercept') plt.show()
def pv(forecast, analysis, variable, levels, **kwargs): pv_f = convert.calc(variable, forecast, levels=levels)[0] pv_a = convert.calc(variable, analysis, levels=levels)[0] err = pv_f - pv_a axes = [] # Initialise the plot fig = plt.figure(figsize=(18, 20)) axes.append(plt.subplot2grid((25, 4), (0, 0), colspan=2, rowspan=10)) im = make_pv_plot(pv_f, **kwargs) plt.title('Forecast') axes.append(plt.subplot2grid((25, 4), (0, 2), colspan=2, rowspan=10)) im = make_pv_plot(pv_a, **kwargs) plt.title('Analysis') ax = plt.subplot2grid((25, 4), (10, 1), colspan=2, rowspan=1) cbar = plt.colorbar(im, cax=ax, orientation='horizontal') axes.append(plt.subplot2grid((25, 4), (13, 1), colspan=2, rowspan=10)) im = iplt.pcolormesh(err, vmin=-5, vmax=5, cmap='coolwarm') iplt.contour(pv_f, [2], colors='k', linewidths=2) iplt.contour(pv_a, [2], colors='k', linewidths=2, linestyles='--') add_map() plt.title('Forecast Minus Analysis') ax = plt.subplot2grid((25, 4), (23, 1), colspan=2, rowspan=1) cbar = plt.colorbar(im, cax=ax, orientation='horizontal') for n, ax in enumerate(axes): ax.set_title(ascii_lowercase[n].ljust(20)) plt.show()
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, **kwargs): """Calculate and plot the distance from the tropopause to cloud """ pv = convert.calc('ertel_potential_vorticity', cubes) cl = convert.calc('mass_fraction_of_cloud', cubes) # Get altitude as a cube z = grid.make_cube(pv, 'altitude') # Add pv and cloud as coordinates to the altitude cube pv = grid.make_coord(pv) z.add_aux_coord(pv, [0, 1, 2]) cl = grid.make_coord(cl) z.add_aux_coord(cl, [0, 1, 2]) # Calculate the height of the cloud top z_cloud = interpolate.to_level(z, mass_fraction_of_cloud=[1e-5])[0] # Calculate the height of the tropopause z_pv2 = interpolate.to_level(z, ertel_potential_vorticity=[2])[0] # Calculate the distance from tropopause to cloud dz = z_pv2.data - z_cloud.data dz = z_pv2.copy(data=dz) # Plot plot.pcolormesh(dz, **kwargs) plt.show()
def get_startpoints(cubes): """Find all points within 1km of the tropopause that have a negative PV anomaly """ # Find the tropopause height pv = convert.calc('ertel_potential_vorticity', cubes) grid.add_hybrid_height(pv) z = grid.make_cube(pv, 'altitude').data zpv2 = get_tropopause_height(pv).data * np.ones_like(z) # Find point below the tropopause tropopause_relative = np.logical_and(z < zpv2, z > zpv2 - 2000) # Find negative pv anomalies diff = convert.calc('total_minus_advection_only_pv', cubes) negative_pv = diff.data < -1 # Combine criteria criteria = np.logical_and(negative_pv, tropopause_relative) # Get indices where criterion is met indices = np.where(criteria) # Convert to lon, lat, z longitude = pv.coord('grid_longitude').points lons = np.array([longitude[idx] for idx in indices[2]]) latitude = pv.coord('grid_latitude').points lats = np.array([latitude[idx] for idx in indices[1]]) height = pv.coord('level_height').points altitude = np.array([height[idx] for idx in indices[0]]) # Make start points array start_points = np.array([lons, lats, altitude]).transpose() return start_points
def make_plot(forecast, analysis, variable, levels, units, errlevs, clevs, cmap='coolwarm', mask=None): # Extract data and errors f = convert.calc(variable, forecast, levels=levels)[0] a = convert.calc(variable, analysis, levels=levels)[0] err = f - a for cube in [f, a, err]: cube.convert_units(units) if mask is not None: for cube in [f, a]: cube.data = np.ma.masked_where(mask, cube.data) # Plot error iplt.contourf(err, errlevs, cmap=cmap, extend='both') add_map() cbar = plt.colorbar(orientation='horizontal', spacing='proportional') errlevs.append(0) cbar.set_ticks(errlevs) cbar.set_label(units) # Overlay forecast and analysis cs = iplt.contour(f, clevs, colors='k', linewidths=2) iplt.contour(a, clevs, colors='k', linewidths=2, linestyles='--') plt.clabel(cs, fmt='%1.0f', colors='k') return
def main(): # Load the variables cubes = forecast.set_lead_time(hours=18) x = convert.calc(names, cubes) surface = convert.calc('boundary_layer_height', cubes) # Mask points within 100 gridpoints of land z = convert.calc('altitude', cubes) zm = filters.maximum_filter(z[0].data, 100) mask = zm > 20 # Interpolate relative to boundary layer height output = diagnostics.profile(x, surface, dz, mask=mask) # Plot the variables for cube in output: c = second_analysis.all_diagnostics[cube.name()] iplt.plot(cube, cube.coord('distance_from_boundary_layer_height'), color=c.color, linestyle=c.linestyle, label=c.symbol) plt.axvline(color='k') plt.axhline(color='k') legend(key=second_analysis.get_idx, loc='best', ncol=2) plt.show() return
def height(cubes): # Calculate the tropopause height pv = convert.calc('ertel_potential_vorticity', cubes) q = convert.calc('specific_humidity', cubes) trop, fold_t, fold_b = tropopause.dynamical(pv, q) return trop, fold_t, fold_b
def main(cubes): lon, lat = grid.true_coords(cubes[0]) z300 = convert.calc('altitude', cubes, levels=('equivalent_potential_temperature', [300]))[0] z300.convert_units('km') mslp = convert.calc('air_pressure_at_sea_level', cubes) mslp.convert_units('hPa') # Plot overview plot.contourf(z300, np.linspace(0, 10, 11)) cs = iplt.contour(mslp, np.linspace(950, 1050, 11), colors='k') plt.clabel(cs, fmt='%1.0f') # Warm Sector warm_sector = z300.data.mask plim = mslp.data < 1000 loc = np.logical_and(lon > -10, lon < 5) ws_mask = np.logical_and(np.logical_and(warm_sector, loc), plim) ws_mask = mslp.copy(data=ws_mask) iplt.contour(ws_mask, linestyles='--', colors='r') # Cold Sector cold_sector = z300.data < 5 loc = np.logical_and(loc, lat < 65) cs_mask = np.logical_and(np.logical_and(cold_sector, loc), plim) cs_mask = mslp.copy(data=cs_mask) iplt.contour(cs_mask, linestyles='--', colors='b') plt.title(r'$z(\theta_e = 300)$') return
def pv_tracer(cubes, name, vmin=-2, vmax=2, cmap='coolwarm'): cube = convert.calc(name, cubes) epv = convert.calc('ertel_potential_vorticity', cubes) adv = convert.calc('advection_only_pv', cubes) plot.pcolormesh(cube, pv=epv, vmin=vmin, vmax=vmax, cmap=cmap) adv.data = np.abs(adv.data) iplt.contour(adv, [2], colors='k', linestyle='--') return
def mass_integrals(cubes, x, y, glat, gridpoints, theta_level, dtheta): """ Args: cubes (iris.cube.CubeList): x (np.Array): Circuit longitudes y (np.Array): Circuit latitudes glat (np.array): Grid latitudes gridpoints(np.Array): Array of gridpoint longitudes and latitudes of shape (ngp, 2) theta_level: dtheta (int): Isentrope spacing used to calculate volume integrals Returns: """ # Include points within circuit boundary points = np.array([x, y]).transpose() pth = Path(points) # Mask all points that are not contained in the circuit mask = np.logical_not(pth.contains_points(gridpoints).reshape(glat.shape)) # Area = r**2 cos(phi) dlambda dphi levels = ('air_potential_temperature', [theta_level - dtheta / 2.0, theta_level, theta_level + dtheta / 2.0]) zth = convert.calc('altitude', cubes, levels=levels) area = (a + zth[1]) ** 2 * np.cos(np.deg2rad(glat)) * np.deg2rad(0.11) ** 2 area.units = 'm^2' area.rename('area') total_area = integrate(area, mask) # Volume = area * dz volume = area * (zth[2] - zth[0]) volume.rename('volume') total_volume = integrate(volume, mask) # Mass = density * volume levels = ('air_potential_temperature', [theta_level]) density = convert.calc('air_density', cubes, levels=levels)[0] mass = density * volume mass.rename('mass') total_mass = integrate(mass, mask) # Circulation = \int rho.pv.dv / dtheta pv = convert.calc('ertel_potential_vorticity', cubes, levels=levels)[0] pv.convert_units('m^2 K s-1 kg-1') pv_substance = pv * mass circulation = integrate(pv_substance, mask) / dtheta circulation.rename('mass_integrated_circulation') return total_area, total_volume, total_mass, circulation
def make_plots(forecast, analysis, variable, levels, units, errlevs, clevs, cmap1='plasma', cmap='coolwarm', mask=None): # Extract data and errors f = convert.calc(variable, forecast, levels=levels)[0] a = convert.calc(variable, analysis, levels=levels)[0] err = f - a for cube in [f, a, err]: cube.convert_units(units) if mask is not None: for cube in [f, a]: cube.data = np.ma.masked_where(mask, cube.data) # Initialise the plot plt.figure(figsize=(18, 15)) # Plot absolute values plt.subplot2grid((25, 4), (0, 0), colspan=2, rowspan=10) im = iplt.contourf(f, clevs, extend='both', cmap=cmap1) #iplt.contour(f, [2], colors='k') plt.title('(a)'.ljust(28) + 'Forecast'.ljust(35)) add_map() plt.subplot2grid((25, 4), (0, 2), colspan=2, rowspan=10) im = iplt.contourf(a, clevs, extend='both', cmap=cmap1) #iplt.contour(a, [2], colors='k', linestyles='--') plt.title('(b)'.ljust(28) + 'Analysis'.ljust(35)) add_map() ax = plt.subplot2grid((25, 4), (10, 1), colspan=2, rowspan=1) cbar = plt.colorbar(im, cax=ax, orientation='horizontal') cbar.set_label(units) # cbar.set_ticks(range(11)) # Plot error plt.subplot2grid((25, 4), (13, 1), colspan=2, rowspan=10) im = iplt.contourf(err, errlevs, cmap=cmap, extend='both') #iplt.contour(f, [2], colors='k') #iplt.contour(a, [2], colors='k', linestyles='--') plt.title('(c)'.ljust(20) + 'Forecast Minus Analysis.'.ljust(38)) add_map() ax = plt.subplot2grid((25, 4), (23, 1), colspan=2, rowspan=1) cbar = plt.colorbar(im, cax=ax, orientation='horizontal', spacing='proportional') errlevs.append(0) cbar.set_ticks(errlevs) cbar.set_label(units) return
def main(cubes): pv = convert.calc('air_potential_temperature', cubes, levels=('ertel_potential_vorticity', [2]))[0] theta = convert.calc('air_potential_temperature', cubes, levels=('air_pressure', [85000]))[0] plot.pcolormesh(theta, vmin=250, vmax=300) iplt.contour(pv, [300, 320], colors='k') plt.show() return
def main(cubes): mass = convert.calc('mass', cubes) water = convert.calc('mass_fraction_of_water', cubes) total_water = mass * water tcw = total_water.collapsed('atmosphere_hybrid_height_coordinate', SUM) mslp = convert.calc('air_pressure_at_sea_level', cubes) mslp.convert_units('hPa') plot.pcolormesh(tcw, vmin=0, vmax=5e9, cmap='Greys_r') iplt.contour(mslp, np.linspace(950, 1050, 11), colors='k', linewidths=2) plt.show() return
def forward_trajectories(forecast): """Calculate 48 hour forward trajectories from low levels Start trajectories from all points below 2km """ cubes = forecast.set_lead_time(hours=48) z = convert.calc('altitude', cubes) theta = convert.calc('air_potential_temperature', cubes) theta_adv = convert.calc('advection_only_theta', cubes) pv = convert.calc('ertel_potential_vorticity', cubes) lon, lat = grid.true_coords(pv) glon, glat = grid.get_xy_grids(pv) time = grid.get_datetime(pv) nz, ny, nx = pv.shape eqlats = rossby_waves.eqlats cs = iris.Constraint(time=time) with iris.FUTURE.context(cell_datetime_objects=True): eqlat = eqlats.extract(cs)[0] # Interpolate to the theta and PV surfaces eqlat = interpolate.main(eqlat, ertel_potential_vorticity=2) eqlat = interpolate.main(eqlat, potential_temperature=theta.data.flatten()) # Define the start points trainp = [] for k in range(nz): print(k) for j in range(ny): for i in range(nx): if (theta_adv.data[k, j, i] < 300 < theta.data[k, j, i] and pv.data[k, j, i] < 2 and lat[j, i] > eqlat.data[k * ny * nx + j * nx + i]): trainp.append([glon[j, i], glat[j, i], z.data[k, j, i]]) trainp = np.array(trainp) plot.pcolormesh(pv[33], vmin=0, vmax=10, cmap='cubehelix_r', pv=pv[33]) plt.scatter(trainp[:, 0], trainp[:, 1]) plt.show() # Calculate the trajectories tracers = ['air_potential_temperature', 'air_pressure'] traout = caltra.caltra(trainp, mapping, fbflag=-1, tracers=tracers) # Save the trajectories traout.save(datadir + 'backward_trajectories.pkl')
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 create_startf(cubes, theta_level, output_file): """Creates a startfile for lagranto for the whole grid on a single isentropic surface Reference date 20111129_2300 / Time range 0 min time lon lat p level --------------------------------------- 0.00 -10.000 50.000 258 320.000 """ # Find pressure on theta level P = convert.calc('air_pressure', cubes, levels=('air_potential_temperature', theta_level))[0].data # Get longitude and latitude lon, lat = grid.true_coords(P) # Create startfile with open(output_file, 'w') as output: output.write('Reference date 20111129_2300 / Time range 0 min\n') output.write('\n') output.write(' time lon lat p level\n') output.write('---------------------------------------\n') output.write('\n') ny, nx = P.shape for j in xrange(ny): for i in xrange(nx): output.write(' 0.00 ' + str(round(lon[j, i], 3)) + ' ' + str(round(lat[j, i], 3)) + ' ' + str(round(P[j, i] / 100.0, 0)) + ' ' + str(theta_level) + '\n\n')
def create_startpoints(cubes, coordinate, values): """Create an array of startpoints Output array has shape Nx3 where N is the number of startpoints and the 3 indices are for longitude, latitude and altitude. Args: cubes (iris.cube.CubeList) Returns: train (np.array): The input array to trajectory calculations """ # Get the values of altitude at the given coordinate P = convert.calc(coordinate, cubes) z = grid.make_cube(P, 'altitude') z.add_aux_coord(grid.make_coord(P), [0, 1, 2]) z500 = interpolate.to_level(z, **{coordinate: values})[0].data lon, lat = grid.get_xy_grids(P) # Convert the 2d arrays to an Nx3 array train = np.array([lon.flatten(), lat.flatten(), z500.flatten()]).transpose() return train
def ridges_troughs(cubes): thetapv2 = convert.calc('air_potential_temperature', cubes, levels=('ertel_potential_vorticity', [2]))[0] ridges, troughs = rossby_waves.make_nae_mask(thetapv2, year=2009) return ridges, troughs
def create_startpoints(cubes, levels, stride=1): """Create an array of startpoints Output array has shape Nx3 where N is the number of startpoints and the 3 indices are for longitude, latitude and altitude. Args: cubes (iris.cube.CubeList) Returns: train (np.array): The input array to trajectory calculations """ # Get the values of altitude at the given coordinate z = convert.calc('altitude', cubes, levels=levels) # Get the grid latitude and longitude as 2d arrays lon, lat = grid.get_xy_grids(z) # Convert the 2d arrays to an Nx3 array nz = z.shape[0] lon = np.tile(lon[::stride, ::stride].flatten(), nz) lat = np.tile(lat[::stride, ::stride].flatten(), nz) z = z.data[:, ::stride, ::stride].flatten() train = np.array([lon, lat, z]).transpose() return train
def main(cubes): """Find all points within 1km of the tropopause that have a negative PV anomaly """ # Find negative pv anomalies diff = convert.calc('total_minus_advection_only_pv', cubes) negative_pv = diff.data < -1 # Find the tropopause height ztrop, fold_t, fold_b = tropopause.height(cubes) # Find point below the tropopause z = diff.coord('altitude').points tropopause_relative = np.logical_and(z < ztrop, z > ztrop - 2000) # Combine criteria criteria = np.logical_and(negative_pv, tropopause_relative) # Get indices where criterion is met indices = np.where(criteria) # Convert to lon, lat, z longitude = diff.coord('grid_longitude').points lons = np.array([longitude[idx] for idx in indices[2]]) latitude = diff.coord('grid_latitude').points lats = np.array([latitude[idx] for idx in indices[1]]) height = grid.extract_dim_coord(diff, 'z').points altitude = np.array([height[idx] for idx in indices[0]]) # Scatterplot the locations fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.scatter(lons, lats, altitude) plt.show()
def main(cubes, dz, name, **kwargs): """Produces cross section plots above and below the tropopause """ # Extract cube to be plotted cube = convert.calc(name, cubes) # Find the height of the tropopause ztrop, fold_t, fold_b = tropopause.height(cubes) # Produce a new co-ordinate above and below the tropopause ny, nx = ztrop.shape new_coord = np.zeros([3, ny, nx]) new_coord[0, :, :] = ztrop.data - dz new_coord[1, :, :] = ztrop.data new_coord[2, :, :] = ztrop.data + dz # Interpolate the cubes to be plotted to the coordinate above and below the # tropopause plotcube = interpolate.to_level(cube, altitude=new_coord) # Plot the cross sections for n in xrange(3): plt.figure() plot.pcolormesh(plotcube[n], **kwargs) plt.show()
def make_plot(cubes, rings, wcb, theta_level, n): # Plot a map at verification time levels = ('air_potential_temperature', [theta_level]) pv = convert.calc('ertel_potential_vorticity', cubes, levels=levels)[0] plot.pcolormesh(pv, vmin=-2, vmax=2, cmap='coolwarm') iplt.contour(pv, [0, 2], colors='k', linewidths=2) add_map() # Load the trajectories x = wcb['grid_longitude'] - 360 y = wcb['grid_latitude'] c = wcb['air_potential_temperature'] # Plot the 3d trajectory positions plt.scatter(x[:, -n], y[:, -n], c=c[:, -n], vmin=300, vmax=340, cmap='coolwarm') # Plot the isentropic boundary x = rings['grid_longitude'] - 360 y = rings['grid_latitude'] plt.plot(x[:, -n], y[:, -n], color='r', linewidth=3) 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 make_plots(field, cubes, levels, path): name = field.pop("name") cube = convert.calc(name, cubes, levels=(levels["name"], levels["values"])) for n, level in enumerate(levels["values"]): plot.pcolormesh(cube[n], **field) plt.savefig("{}{}_{}_{}.png".format(path, name, levels["name"], levels["values"][n])) plt.clf()
def main(cubes): pv = convert.calc('ertel_potential_vorticity', cubes, levels=levels)[0] adv = convert.calc('advection_only_pv', cubes, levels=levels)[0] for n, name in enumerate([ 'sum_of_physics_pv_tracers', 'epsilon', 'dynamics_tracer_inconsistency', 'residual_pv' ]): cube = convert.calc(name, cubes, levels=levels)[0] m = n / 2 ax = plt.subplot2grid((2, 2), (n - 2 * m, m)) iplt.contourf(cube, clevs, cmap=cmap) add_map() iplt.contour(pv, [2], colors='k', linestyles='-') iplt.contour(adv, [2], colors='k', linestyles='-') plt.show()
def main(): lead_time = 48 levels = ('air_potential_temperature', [320]) forecast = case_studies.iop5_extended.copy() cubes = forecast.set_lead_time(hours=lead_time) dtheta = convert.calc('total_minus_advection_only_theta', cubes, levels=levels)[0] pv = convert.calc('ertel_potential_vorticity', cubes, levels=levels)[0] closed_loop, points = get_points(dtheta.copy(), pv.copy()) closed_loop = increase_circuit_resolution(closed_loop, 25000) make_plot(dtheta, pv, closed_loop, vmin=-20, vmax=20, cmap='coolwarm') 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 compare_pv(cubes, rdf_pv, p_level, *args, **kwargs): # Calculate required variables pv = convert.calc('ertel_potential_vorticity', cubes, levels=('air_pressure', [p_level]))[0] adv = convert.calc('advection_only_pv', cubes, levels=('air_pressure', [p_level]))[0] qsum = convert.calc('sum_of_physics_pv_tracers', cubes, levels=('air_pressure', [p_level]))[0] diff = pv - qsum diff.rename('pv_minus_physics_pv_tracers') # Plot both figures for cube in [diff, adv, rdf_pv]: plt.figure() plot.contourf(cube, *args, **kwargs) return
def _single_fit(coord, subdomain, dz, function, **kwargs): cubes = second_analysis.get_data(coord, subdomain) pv = convert.calc(variable, cubes) x, y, dy = function(pv, coord, dz) popt, pcov, rmse = fit_curve(x, y, dy) print(popt, rmse) plot_fit(x, y, dy, popt, **kwargs) return popt, rmse