def trajectory_2D_3D_displacement_difference(k = 0, folder = 'IOP3/T42', strapp = ''): # figure 4 basetime = [datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12)] basetime_str = basetime[k].strftime('%Y%m%d_%H') t3 = load('/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble_new'.format(basetime_str) + strapp) t2 = load('/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folder + '/inflow/{}_2DTrajectoryEnsemble'.format(basetime_str) + strapp) pts = len(t3.data[:, 0, 0]) traj23diffs = np.zeros([pts, 3, 4]) for i, t in enumerate([0, 5, -1]): traj23diffs[:, i, 0] = t2.data[:, t, 2] - t3.data[:, t, 3] traj23diffs[:, i, 1] = t2.data[:, t, 0] - t3.data[:, t, 0] traj23diffs[:, i, 2] = t2.data[:, t, 1] - t3.data[:, t, 1] traj23diffs[:, i, 3] = (traj23diffs[:, i, 1]**2 + traj23diffs[:, i, 2]**2)**0.5 for i, t in enumerate([0, 5, -1]): plt.figure(figsize = (10, 8)) plt.suptitle('Differences at ' + str(t3.times[t])) for j, name in enumerate([['longitude_difference', -40, 20], ['latitude_difference', -10, 10], ['total_displacement', -5, 40]]): plt.subplot(2, 2, j+1) plt.hist2d(traj23diffs[:, i, j+1], traj23diffs[:, i, 0], bins = 50, range = [[name[1], name[2]], [-10, 35]], cmap = 'binary', norm = LogNorm()) plt.colorbar()#ticks = [1, 3, 10, 30, 100, 300, 1000, 3000, 10000]) plt.ylabel('theta_difference') plt.xlabel(name[0]) plt.subplot(2, 2, 4) plt.hist2d(traj23diffs[:, i, 1], traj23diffs[:, i, 2], bins = 50, range = [[-40, 20], [-10, 10]], cmap = 'binary', norm = LogNorm()) plt.colorbar()#ticks = [1, 3, 10, 30, 100, 300, 1000, 3000, 10000]) plt.xlabel('longitude_displacement') plt.ylabel('latitude_displacement') plt.savefig('/home/users/bn826011/NAWDEX/From N Drive/2019_figs/' + folder[:4] + '/traj23diffs_' + str(t) + 'x6_hours_before_new.jpg') plt.show() return t2, t3, traj23diffs
def main_cc(k = 0, filtersize = 30, theta_level = 325, dtheta = 1, split = False, folder = 'IOP3/T42', strapp = ''): basetime = [datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12)] basetime_str = basetime[k].strftime('%Y%m%d_%H') #datadir = '/export/cloud/migrated-NCASweather/ben/nawdex/mi-ar482/{}/'.format(basetime_str) datadir = '/storage/silver/NCAS-Weather/ben/nawdex/mi-ar482//{}/'.format(basetime_str) TrB = load(save_dir + folder + '/{}_TrajectoryEnsemble_backward'.format(basetime_str) + strapp) TrF = load(save_dir + folder + '/{}_TrajectoryEnsemble_forward'.format(basetime_str) + strapp) start_time = [-1*TrB.relative_times[-1]] # time at which trajectories were initialised trajectories = TrB.__add__(TrF) # trajectories = load(save_dir + folder + '/{}_TrajectoryEnsemble_forward'.format(basetime_str) + strapp) # trajectories = TrB # start_time = [trajectories.relative_times[0]] mapping = {} for t in trajectories.times: leadtimehr = np.int((t - basetime[k]).total_seconds()) / 3600 fn = 'prodm_op_gl-mn_{0}_d{1:03d}_thgrid.pp'.\ format(basetime_str, 12 * (leadtimehr / 12)) mapping[t] = datadir + fn fcast = forecast.Forecast(basetime[k], mapping) if split == True: strapp = strapp + '_splitLW'#'_split' calc_circulation(trajectories, fcast, theta_level, dtheta, start_time, filtersize, k, split, folder, strapp, basetime_str)
def main(): path = '/projects/diamet/lsaffi/' job = 'iop5_extended' forecast = case_studies.iop5_extended.copy() theta_level = 320 cluster = 3 dt1 = timedelta(hours=0) dt2 = timedelta(hours=-48) # Load the bounding isentropic trajectories name = 'isentropic_backward_trajectories_from_outflow_boundary' rings = trajectory.load(path + job + '/' + name + '.pkl') rings = rings.select('air_potential_temperature', '==', theta_level) print(len(rings)) # Load the 3d trajectories name = 'backward_trajectories_from_outflow_coarse' trajectories = trajectory.load(datadir + job + '/' + name + '.pkl') print(len(trajectories)) # Only include trajectories that stay in the domain trajectories = trajectories.select('air_pressure', '>', 0) print(len(trajectories)) trajectories = trajectories.select('air_potential_temperature', '==', theta_level - 2.5, time=[dt1]) print(len(trajectories)) # Composite trajectory clusters if cluster is not None: if theta_level is not None: path = datadir + job + '/' + name + '_' + str(theta_level) + 'K' else: path = datadir + job + '/' + name trajectories = select_cluster(cluster, trajectories, path) print(len(trajectories)) plt.figure() for n, cubes in enumerate(forecast): print(n) plt.clf() make_plot(cubes, rings, trajectories, theta_level, n + 2) plt.savefig(plotdir + 'isentropic_rings_' + str(theta_level) + 'K_' + str(n).zfill(3) + '.png') return
def single_hist(k = 0, levs = 3, theta_0 = [320, 325, 310, 310], t = 0, folder = 'IOP3/T42', strapp = ''): basetime = [datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12)] basetime_str = basetime[k].strftime('%Y%m%d_%H') Tr3 = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble'.format(basetime_str) + strapp) bins = np.linspace(-200, 650, 18) #bins = np.linspace(-10, 40, 26) plt.figure(figsize = (5, 3)) Tall = Tr3.select('air_potential_temperature', '!=', -1000) #only those which remain in domain plt.hist((Tall.data[:, -(t+1), 4] - Tall.data[:, 0, 4])/100, bins = bins) #plt.title(folder + '_' + strapp) #plt.title('Started at all surfaces') #plt.xlabel('theta, K') plt.xlabel('pressure, hPa') plt.ylabel('number of trajectories') plt.savefig('IOP3_T60' + strapp + '_change_pressure_hist_t=' + str(t) + '.png') plt.show()
def main(): job = 'iop5_extended' name = 'backward_trajectories_from_outflow' variable = 'air_potential_temperature' cluster = None plotname = plotdir + job + '_' + name + '_histogram_' + variable # Load the trajectories trajectories = trajectory.load(datadir + job + '/' + name + '.pkl') print(len(trajectories)) # Only include trajectories that stay in the domain trajectories = trajectories.select('air_pressure', '>', 0) print(len(trajectories)) # Composite trajectory clusters if cluster is not None: path = datadir + job + '/' + name trajectories = select_cluster(cluster, trajectories, path) plotname += '_cluster' + str(cluster) print(len(trajectories)) make_plot(trajectories, variable) plt.savefig(plotname + '.png') plt.show() return
def main(): job = 'iop5_extended' name = 'backward_trajectories_from_outflow_coarse' trajectories = trajectory.load(datadir + job + '/' + name + '.pkl') trajectories = trajectories.select('air_pressure', '>', 0) dt = timedelta(hours=0) theta_level = 320 trajectories = trajectories.select('air_potential_temperature', '>', theta_level - 2.5, time=[dt]) trajectories = trajectories.select('air_potential_temperature', '<', theta_level + 2.5, time=[dt]) print(len(trajectories)) # Perform the clustering #cluster_array = make_cluster_array(trajectories) #clusters = perform_clustering(cluster_array, max_dist=4) #plt.savefig(plotdir + job + '_' + name + '_cluster_info.png') #np.save(datadir + job + '/' + name + '_' + str(theta_level) + 'K_clusters.npy', clusters) clusters = np.load(datadir + job + '/' + name + '_' + str(theta_level) + 'K_clusters.npy') # Display output nclusters = len(set(clusters)) print('Number of clusters', nclusters) plot_clusters(trajectories, clusters) plt.savefig(plotdir + job + '_' + name + '_clusters_xy.png') plt.show() return
def heating_hist(k=0, levs=3, theta_0=[320, 325, 310, 310], t=0, folder='IOP3/T42', strapp=''): basetime = [ datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12) ] basetime_str = basetime[k].strftime('%Y%m%d_%H') #Tr3 = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble'.format(basetime_str) + strapp) Tr3 = load('/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble'.format(basetime_str) + strapp) bins = np.linspace(-10, 30, 21) plt.figure(figsize=(13, 9)) Tall = Tr3.select('air_potential_temperature', '!=', -1000) #only those which remain in domain plt.subplot(int(levs / 2) + 1, 2, 1) curve = plt.hist(Tall.data[:, 0, 3] - Tall.data[:, -(t + 1), 3], bins=bins) #plt.title(folder + '_' + strapp) plt.title('Started at all surfaces') plt.xlabel('Delta theta') for i in xrange(levs): theta = theta_0[k] + i * 5 Tt = Tall.select('air_potential_temperature', '>=', theta - 2.5, time=[datetime.timedelta(hours=0)]) Tt = Tt.select('air_potential_temperature', '<', theta + 2.5, time=[datetime.timedelta(hours=0)]) # those which remain in domain that start on desired theta surface plt.subplot(int(levs / 2) + 1, 2, 2 + i) plt.hist(Tt.data[:, 0, 3] - Tt.data[:, -(t + 1), 3], bins=bins) plt.title('Started at ' + str(theta) + 'K surface') plt.xlabel('Delta theta') plt.savefig('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/inflow/delta_theta_histograms_t=' + str(t) + strapp + '.png') #plt.savefig('IOP3_T42_2x2_hist_t=' + str(t) + '.png') plt.show() return curve
def single_plume(k = 0, levs = 3, theta_0 = [320, 325, 310, 310], trajs = 50, folder = 'IOP3/T42', strapp = '', add = ''): basetime = [datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12)] basetime_str = basetime[k].strftime('%Y%m%d_%H') TrB = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble'.format(basetime_str) + strapp) TrF = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble_fw'.format(basetime_str) + strapp) Tr3 = TrB.__add__(TrF) # Tr3 = TrB #deftime = len(TrB.times) - 1 plt.figure(figsize = (5, 3)) Tall = Tr3.select('air_potential_temperature', '!=', -1000) #only those which remain in domain for i in xrange(trajs): i = random.randint(0, len(Tall)-1) plt.plot(Tall.times, Tall.data[i, :, 5])#4 # Tmean = np.mean(Tall.data[:, :, 5], axis = 0) # plt.plot(Tall.times, Tmean, color = 'k', linewidth = 3) #plt.ylabel('theta, K') plt.ylabel('specific_humidity') plt.xlabel('time') pg = plt.gca() fmt = DateFormatter('\n%m/%d') fmt2 = DateFormatter('%H') majorLocator = DayLocator(interval=1) minorLocator = HourLocator(range(0, 24, 6)) pg.xaxis.set_major_formatter(fmt) pg.xaxis.set_minor_formatter(fmt2) pg.xaxis.set_minor_locator(minorLocator) pg.xaxis.set_major_locator(majorLocator) #pg.invert_yaxis() plt.savefig('IOP3_T60' + strapp + '50_random_3D-trajectories_humidity' + add + '.png') plt.show()
def pv_ascent(k = 0, levs = 3, theta_0 = [320, 325, 310, 310], trajs = 50, asc = 10, voltimes = [[12, 42], [6, 36], [12, 42], [0, 24]], folder = 'IOP3/T42', strapp = '', add = ''): basetime = [datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12)] basetime_str = basetime[k].strftime('%Y%m%d_%H') TrB = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble'.format(basetime_str) + strapp) # TrF = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble_fw'.format(basetime_str) + strapp) # Tr3 = TrB.__add__(TrF) Tr3 = TrB #times = [datetime.timedelta(hours = voltimes[k][1]), datetime.timedelta(hours = voltimes[k][0])] times = [datetime.timedelta(hours = 0), datetime.timedelta(hours = (voltimes[k][0]-voltimes[k][1]))] #deftime = len(TrB.times) - 1 plt.figure(figsize = (5, 3)) Tall = Tr3.select('air_potential_temperature', '!=', -1000) #only those which remain in domain Tasc = Tall.select('air_potential_temperature', '<', asc, time = times) #only those which experience 10K of heating for i in xrange(trajs): i = random.randint(0, len(Tasc)-1) plt.plot(Tasc.times, Tasc.data[i, :, 8])#4 Tmean = np.mean(Tasc.data[:, :, 8], axis = 0) plt.plot(Tasc.times, Tmean, color = 'k', linewidth = 3) #plt.ylabel('theta, K') plt.ylabel('PV') plt.xlabel('time') pg = plt.gca() fmt = DateFormatter('\n%m/%d') fmt2 = DateFormatter('%H') majorLocator = DayLocator(interval=1) minorLocator = HourLocator(range(0, 24, 6)) pg.xaxis.set_major_formatter(fmt) pg.xaxis.set_minor_formatter(fmt2) pg.xaxis.set_minor_locator(minorLocator) pg.xaxis.set_major_locator(majorLocator) #pg.invert_yaxis() plt.savefig('easy_to_find/' + folder + strapp + '50_random_3D-trajectories_PV_asc' + str(asc) + add + '.png') #plt.savefig('easy_to_find/' + folder + strapp + 'PV_asc' + str(asc) + add + '.png') plt.show()
def outflow_from_old(k = 1, lag = 1, folderin = 'IOP5/T42', folderout = 'IOP5/T42-6', strapp = ''): "define outflow volume from a trajectory ensemble already run" "To test consistency" "Taken 6*lag hours before the definition of the given trajectory" basetime = [datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12)] basetime_str = basetime[k].strftime('%Y%m%d_%H') TrB = load('/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folderin + '/{}_TrajectoryEnsemble_backward'.format(basetime_str)) outflow_volume = TrB.data[:, lag, :3] np.save('/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folderout + '/' + TrB.times[lag].strftime("%m%d_%H") + strapp + '.npy', outflow_volume) return
def outflow_on_altitude(k = 0, folder = 'IOP3/T42', strapp = ''): "define outflow volume from a trajectory ensemble already run" "To get set of points on altitude coord to then run backwards 3d" basetime = [datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12)] basetime_str = basetime[k].strftime('%Y%m%d_%H') Tr2 = load('/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folder + '/inflow/{}_2DTrajectoryEnsemble'.format(basetime_str) + strapp) llalt = np.array([True, True, False, True, False, False, False, False]) outflow_volume = Tr2.data[:, 0, llalt] np.save('/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folder + '/inflow/' + basetime_str + strapp + 'initial_grid_new.npy', outflow_volume) return
def main(): job = 'iop5_extended' name = 'backward_trajectories_from_outflow_coarse' variable = 'total_minus_advection_only_pv' theta_level = 320 cluster = 3 plotname = plotdir + job + '_' + name + '_spread_' + variable # Load the trajectories trajectories = trajectory.load(datadir + job + '/' + name + '.pkl') print(len(trajectories)) # Only include trajectories that stay in the domain trajectories = trajectories.select('air_pressure', '>', 0) print(len(trajectories)) if theta_level is not None: dt = timedelta(hours=0) trajectories = trajectories.select('air_potential_temperature', '>', theta_level - 2.5, time=[dt]) trajectories = trajectories.select('air_potential_temperature', '<', theta_level + 2.5, time=[dt]) print(len(trajectories)) # Composite trajectory clusters if cluster is not None: if theta_level is not None: path = datadir + job + '/' + name + '_' + str(theta_level) + 'K' plotname += '_' + str(theta_level) + 'K' else: path = datadir + job + '/' + name trajectories = select_cluster(cluster, trajectories, path) print(len(trajectories)) plotname += '_cluster' + str(cluster) make_plot(trajectories, variable) plt.savefig(plotname + '.png') plt.show() return
def select_wcb(filename): # Load the trajectories trajectories = trajectory.load(filename) print(len(trajectories)) # Select trajectories that stay in the domain trajectories = trajectories.select('air_pressure', '>', 0) print(len(trajectories)) # Select trajectories that fulfill the ascent criteria dt1 = datetime.timedelta(hours=0) dt2 = datetime.timedelta(hours=48) trajectories = trajectories.select('air_pressure', '>', 60000, time=[dt1, dt2]) print(len(trajectories)) return trajectories
def main(): # Define parameters forecast = case_studies.iop5_extended.copy() job = 'iop5_extended' name = 'isentropic_backward_trajectories_from_outflow_boundary' theta_level = 320 dtheta = 1 # Load trajectories filename = datadir + job + '/' + name + '.pkl' trajectories = trajectory.load(filename) print(len(trajectories)) # Do the calculations over the forecast and save the result calc_circulation(trajectories, forecast, theta_level, dtheta) # Load in saved output and produce plots load_from_files(str(theta_level)) return
def bound_outflow_3D(k = 0, folder = 'IOP3/T42', in_time = 5, min_lev = 320, strapp = '', gmod = False): basetime = [datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12)] basetime_str = basetime[k].strftime('%Y%m%d_%H') Tr3 = load('/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble_new'.format(basetime_str) + strapp) Tr3_inflow = Tr3.select('air_potential_temperature', '>', min_lev - 2.5, time = [datetime.timedelta(hours = -6*in_time)]) inf_area = plt.hist2d(Tr3_inflow.data[:, in_time, 0], Tr3_inflow.data[:, in_time, 1], bins = [360, 90], range = [[0, 360], [0, 90]]) plt.show() if gmod: ia = filters.gaussian_filter(inf_area[0], gmod) else: ia = inf_area[0] cs = plt.contour(np.transpose(ia), [.5]) contours = trop.get_contour_verts(cs) ncon = len(contours[0]) #number of contours lencon = np.zeros(ncon) # empty array of lengths of contorus (in lat/long space) for j in xrange(ncon): print ncon print j lencon[j] = len_con(contours[0][j]) imax = lencon.argmax() # index of longest contour lcontour = contours[0][imax] # longest contour # don't worry about closed-ness points = increase_nodes(lcontour, resolution = .25) np.save('/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folder + '/outflow_bound_3D_less_than_' + str(min_lev) + 'K_gmod.npy', points)
def calc_density(k=0, thlevs=[[320, 325, 330], [325, 330, 335], [310, 315, 320], [310, 315, 320]], plotv=True, folder='IOP3/T42', strapp=''): basetime = [ datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12) ] basetime_str = basetime[k].strftime('%Y%m%d_%H') datadir = '/export/cloud/NCASweather/ben/nawdex/mi-ar482/{}/'.format( basetime_str) TrB = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/{}_TrajectoryEnsemble_backward'.format(basetime_str) + strapp) TrF = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/{}_TrajectoryEnsemble_forward'.format(basetime_str) + strapp) start_time = [-1 * TrB.relative_times[-1]] # time at which trajectories were initialised trajectories = TrB.__add__(TrF) mapping = {} for t in trajectories.times: leadtimehr = np.int((t - basetime[k]).total_seconds()) / 3600 fn = 'prodm_op_gl-mn_{0}_d{1:03d}_thgrid.pp'.\ format(basetime_str, 12 * (leadtimehr / 12)) mapping[t] = datadir + fn fcast = forecast.Forecast(basetime[k], mapping) idcl = iris.cube.CubeList([]) # create empty cube list of isentropic density pvsl = iris.cube.CubeList([]) # and empty cube for pv substance if plotv == True: plt.figure(figsize=(15, 40)) for m, theta_level in enumerate(thlevs[k]): # Select an individual theta level TrEntheta = trajectories.select('air_potential_temperature', '==', theta_level, time=start_time) levels = ('air_potential_temperature', [theta_level]) icl = iris.cube.CubeList([]) pcl = iris.cube.CubeList([]) for n, time in enumerate(TrEntheta.times): cubelist = fcast.set_time(time) #now for some reason I'm having real problems extracting the right time, so u = iris.unit.Unit('hours since 1970-01-01 00:00:00', calendar=iris.unit.CALENDAR_STANDARD) timeh = u.date2num(time) #this puts the time in the same format as in the cubelist cubes = cubelist.extract(iris.Constraint(time=time)) # needed because each file contains two times pv = convert.calc('derived_pv', cubes, levels=levels) mass = convert.calc('mass', cubes, levels=levels) theta = convert.calc('air_potential_temperature', cubes) density = convert.calc('air_density', cubes, levels=levels) #print density coord = grid.make_coord(theta) theta.add_aux_coord(coord, range(theta.ndim)) # add theta as coordinate dtdz = mycalc.multidim(theta, 'altitude', 'z') #print dtdz coord_name, values = levels dzdtcube = interpolate.to_level(dtdz, **{coord_name: values}) dzdtcube.convert_units('meter-kelvin^-1') #print dzdtcube r = dzdtcube * density r.rename('isentropic_density') #print r r.remove_coord('forecast_period') #print r idcl.append(iris.util.new_axis(r, 'time')) # add isentropic density to cube list pvs = pv * mass pvs.rename('pv_substance') pvs.remove_coord('forecast_period') pvsl.append(iris.util.new_axis(pvs, 'time')) #print pvsl[-1] if plotv == True: tlno = len(thlevs[k]) tno = len(TrEntheta.times) plt.subplot(tno, tlno, n * tlno + m + 1) #iplt.contourf(r[0], np.linspace(0, 1000, 21), cmap = 'binary') iplt.contourf(pvs[0], cmap='binary') plt.gca().coastlines(color=[.6, .4, 0]) iplt.contour(pv[0], [2], colors=['r']) TrEnindomain = trajectories.select( 'air_potential_temperature', '==', theta_level, time=[datetime.timedelta(hours=6 * n)]) Leftdomain = TrEntheta.__len__() - TrEnindomain.__len__() if np.shape(TrEntheta) == (0, ): pass elif Leftdomain != 0: #If any of the trajectories have left the domain plt.plot(TrEnindomain.data[:, n, 0] - 360, TrEnindomain.data[:, n, 1], color=[.4, .4, .4], marker='.', ms=.8, mec='k', mfc='k') plt.title(str(Leftdomain) + ' points have left the domain') else: plt.plot(TrEntheta.data[:, n, 0] - 360, TrEntheta.data[:, n, 1], color=[.4, .4, .4], marker='.', ms=.8, mec='k', mfc='k') # plot outflow area, black if n == 0: if Leftdomain != 0: plt.title( str(theta_level) + ' K \n ' + str(Leftdomain) + ' points have left the domain') #label columns with isentropic levels else: plt.title(str(theta_level) + ' K') if m == 0: timedatenow = trajectories.times[n] plt.text(-90, 70, timedatenow.strftime("%d/%m %HUTC"), rotation='vertical') #label rows with dates and times if plotv == True: plt.savefig('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/' + basetime_str + '_' + 'pv_substance' + strapp + '.png') plt.show() #print pvsl pv_substance = pvsl.concatenate_cube() #print pv_substance isentropic_density = idcl.concatenate_cube() both = iris.cube.CubeList([isentropic_density, pv_substance]) iris.save( both, '/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/' + basetime_str + '_isentropic_density' + strapp + '.nc') return isentropic_density, pv_substance
def make_plot(cubes, job, name, levels, theta_level, cluster, **kwargs): plt.figure(figsize=(12, 10)) plotname = plotdir + job + '_' + name + '_map' # Plot a map at verification time pv = convert.calc('ertel_potential_vorticity', cubes, levels=levels)[0] dtheta = convert.calc('total_minus_advection_only_theta', cubes, levels=levels)[0] mslp = convert.calc('air_pressure_at_sea_level', cubes) mslp.convert_units('hPa') plot.pcolormesh(dtheta, vmin=-20, vmax=20, cmap='coolwarm', pv=pv) cs = iplt.contour(mslp, range(950, 1050, 5), colors='k', linewidths=1) plt.clabel(cs, fmt='%1.0f') # Load the trajectories filename = datadir + job + '/' + name + '.pkl' trajectories = trajectory.load(filename) print(len(trajectories)) # Only plot trajectories that stay in the domain trajectories = trajectories.select('air_pressure', '>', 0) print(len(trajectories)) # Select individual clusters of trajectories if cluster is not None: path = datadir + job + '/' + name select_cluster(cluster, trajectories, path) plotname += '_cluster' + str(cluster) if theta_level is not None: plotname += '_' + str(theta_level) + 'K' dt = timedelta(hours=48) trajectories = trajectories.select('air_potential_temperature', '>', theta_level - 2.5, time=[dt]) trajectories = trajectories.select('air_potential_temperature', '<=', theta_level + 2.5, time=[dt]) print(len(trajectories)) x = trajectories.x - 360 y = trajectories.y c = trajectories['altitude'] # Plot each individual trajectory for n in range(len(trajectories)): plot.colored_line_plot(x[n], y[n], c[n], **kwargs) # Mark the start and end point of trajectories plt.scatter(x[:, 0], y[:, 0], c=c[:, 0], linewidths=0.1, zorder=5, **kwargs) plt.scatter(x[:, -1], y[:, -1], c=c[:, -1], linewidths=0.1, zorder=5, **kwargs) plt.colorbar() plt.savefig(plotname + '.png') return
def plot_traj(k = 0, levs = 3, filtersize = 30, field = 'total_minus_adv_only_theta', scatter3D = False, lim = 40, indiv = False, folder = 'IOP3/T42', strapp = ''): "Options for field:" "total_minus_adv_only_theta (default)" "ertel_potential_vorticity" "pv_substance" # recommend limits ~ 1e11 "isentropic_density" # recommend limits ~ 1000 "dPV_: cld, LW, mass, iau, bl, tot, mic, SW, gwd, adv, phl, sol, conv" "adv_only_PV" "total_minus_adv_only_PV" "Or, if 3Dscatter == True:" "air_potential_temperature" "air_pressure" "specific_humidity" "mass_fraction_of_cloud_ice_in_air" "mass_fraction_of_cloud_liquid_water_in_air" "lim is +/- limits of contours coloured distinctly for field, default 40" basetime = [datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12)] basetime_str = basetime[k].strftime('%Y%m%d_%H') #TrB = load('outflow/T42_mfs' + str(filtersize) + '/{}_TrajectoryEnsemble_backward'.format(basetime_str)) #TrF = load('outflow/T42_mfs' + str(filtersize) + '/{}_TrajectoryEnsemble_forward'.format(basetime_str)) TrB = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/{}_TrajectoryEnsemble_backward'.format(basetime_str) + strapp) TrF = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/{}_TrajectoryEnsemble_forward'.format(basetime_str) + strapp) TrEn = TrB.__add__(TrF) tsteps = len(TrEn.times) theta_0 = TrEn.data[0, 0, 2] V = np.linspace(-lim, lim, 35) clpv = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/' + basetime_str + '/prodm_op_gl-mn_' + basetime_str + '_c*_thsfcs_5K.nc', 'ertel_potential_vorticity') clpv[-1] = iris.util.new_axis(clpv[-1], 'time') pvcube = clpv.concatenate_cube() # create cube of PV if field == 'total_minus_adv_only_theta': cldt = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/' + basetime_str + '/prodm_op_gl-mn_' + basetime_str + '_b*_thsfcs_5K.nc', 'total_minus_adv_only_theta') cldt[-1] = iris.util.new_axis(cldt[-1], 'time') fieldcube = cldt.concatenate_cube() # create cube of delta theta elif field == 'ertel_potential_vorticity': fieldcube = pvcube elif field in ['pv_substance', 'isentropic_density']: IOPs = [3, 5, 6, 7] fieldcube = iris.load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP' + str(IOPs[k]) + '/' + basetime_str + '_isentropic_density.nc', field)[0] elif scatter3D == False: #assume user has input the name of a diabatic PV field cldpv = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/' + basetime_str + '/prodm_op_gl-mn_' + basetime_str + '_c*_thsfcs_5K.nc', field) cldpv[-1] = iris.util.new_axis(cldpv[-1], 'time') fieldcube = cldpv.concatenate_cube() # and for PV if scatter3D != False: Tr3 = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble'.format(basetime_str) + strapp) field_no = Tr3.names.index(field) strapp = 'scatter3D_' + strapp if indiv == False: plt.figure(figsize = (levs*5, 40)) for tht in xrange(levs): theta = theta_0 + 5*tht TrEntheta = TrEn.select('air_potential_temperature', '==', theta, time = [-1*TrB.relative_times[-1]]) # This gives the levels at the designated start time if scatter3D != False: Tt = Tr3.select('air_potential_temperature', '>=', theta - 2.5, time = [datetime.timedelta(hours = 0)]) Tt = Tt.select('air_potential_temperature', '<', theta + 2.5, time = [datetime.timedelta(hours = 0)]) Tt = Tt.select(field, '!=', -1000) # points starting from theta level for which field is defined for t in xrange(tsteps): if indiv == False: plt.subplot(tsteps, levs, t*levs + tht + 1) else: plt.figure(figsize = (10, 10)) # for plotting individual frames pvort = pvcube.extract(iris.Constraint(time = TrEn.times[t], air_potential_temperature = theta)) if scatter3D == False: c_field = fieldcube.extract(iris.Constraint(time = TrEn.times[t], air_potential_temperature = theta)) iplt.contourf(c_field, V, cmap = 'seismic', norm = matplotlib.colors.Normalize(-lim, lim)) # plot contours of field, blue & red iplt.contour(pvort, [2], colors = ['g']) # plot 2 PVU contour, green plt.gca().coastlines(color = [.6, .4, 0]) # plot coastlines, dark yellow if scatter3D == True: if t < len(Tt.times): if field == 'air_potential_temperature': norm = matplotlib.colors.Normalize(theta-lim, theta+10) else: norm = matplotlib.colors.Normalize(-lim, lim) plt.scatter(Tt.data[:, -1-t, 0]-360, Tt.data[:, -1-t, 1], c = Tt.data[:, -1-t, field_no], marker = '.', cmap = 'inferno', norm = norm, edgecolors = 'face') TrEnindomain = TrEn.select('air_potential_temperature', '==', theta, time = [datetime.timedelta(hours=6*t)]) Leftdomain = TrEntheta.__len__() - TrEnindomain.__len__() if np.shape(TrEntheta) == (0,): pass elif Leftdomain != 0: #If any of the trajectories have left the domain plt.plot(TrEnindomain.data[:, t, 0]-360, TrEnindomain.data[:, t, 1], color = [.4, .4, .4], marker = '.', ms = .8, mec = 'k', mfc = 'k') plt.title(str(Leftdomain) + ' points have left the domain') else: plt.plot(TrEntheta.data[:, t, 0]-360, TrEntheta.data[:, t, 1], color = [.4, .4, .4], marker = '.', ms = .8, mec = 'k', mfc = 'k') # plot outflow area, black if indiv == True: plt.savefig('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/indv_plts/' + basetime_str + '_' + field + strapp + str(int(theta)) + 'K_t=' + str('{0:02d}'.format(t)) + '.png') #for plotting individual frames if t == 0: if Leftdomain != 0: plt.title(str(theta) + ' K \n ' + str(Leftdomain) + ' points have left the domain') #label columns with isentropic levels else: plt.title(str(theta) + ' K') if tht == 0: timedatenow = TrEn.times[t] plt.text(-90, 70, timedatenow.strftime("%d/%m %HUTC"), rotation = 'vertical') #label rows with dates and times #plt.savefig('outflow/T42_mfs' + str(filtersize) + '/' + basetime_str + 'fulltraj_' + field + '.jpg') if indiv == False: pass
def outflow_grid(k=0, levels=3, hoursafterinit=[42, 36, 42, 24], thlevs=[[320, 325, 330], [325, 330, 335], [310, 315, 320], [310, 315, 320]], folder='IOP3/T42', strapp=''): "This presently defines the grid of points from the sime time that the region is defined" "But by loading the forward trajectories this could easily be adapted to" "define the grid at any time along the trajectory" #save_dir = '/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' save_dir = '/storage/silver/scenario/bn826011/WCB_outflow/Final/' basetime = [ datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12) ] basetime_str = basetime[k].strftime('%Y%m%d_%H') TrB = load(save_dir + folder + '/{}_TrajectoryEnsemble_backward'.format(basetime_str) + strapp) start_time = [datetime.timedelta(hours=0)] # trajectory at definition time datadir = '/export/cloud/migrated-NCASweather/ben/nawdex/mi-ar482/{}/'.format( basetime_str) #hoursafterinit = [42, 42, 42, 72, 96]#42 time = basetime[k] + datetime.timedelta(hours=hoursafterinit[k]) mapping = {} leadtimehr = np.int((time - basetime[k]).total_seconds()) / 3600 fn = 'prodm_op_gl-mn_{0}_d{1:03d}_thgrid.pp'.\ format(basetime_str, 12 * (leadtimehr / 12)) mapping[time] = datadir + fn # dexs = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/20160922_12/' + # 'prodm_op_gl-mn_20160922_12_d*_thsfcs_5K.nc', 'dimensionless_exner_function') # dexs[-1] = iris.util.new_axis(dexs[-1], 'time') # dex = dexs.concatenate_cube() # # temps = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/20160922_12/' + # 'prodm_op_gl-mn_20160922_12_d*_thsfcs_5K.nc', 'air_temperature') # temps[-1] = iris.util.new_axis(temps[-1], 'time') # temp = temps.concatenate_cube() # # lvls = ('air_potential_temperature', thlevs[k]) # # altd = convert.calc('altitude', iris.cube.CubeList([dex, temp]), levels = lvls) # # 3D caltra works on altitude not theta levels # # however I don't know how to get altitude?! # # I think leo's data must've have altitude as a coordinate cubes = iris.load(mapping[time], iris.Constraint(time=time)) plt.figure(figsize=(10, 14)) zc = iris.load( '/export/cloud/migrated-NCASweather/ben/nawdex/mi-ar482/' + basetime_str + '/prodm_op_gl-mn_' + basetime_str + '_d*_thsfcs_5K.nc', 'altitude') zc = zc[:-1].concatenate_cube() # the last time step has different metadata? for kl in xrange(levels): theta_level = thlevs[k][kl] trajectories = TrB.select('air_potential_temperature', '==', theta_level, time=start_time) x = trajectories.x[:, 0] y = trajectories.y[:, 0] # # tlev_cstrnt = iris.Constraint(air_potential_temperature = theta_level) # # altdth = altd.extract(tlev_cstrnt) lvls = ('air_potential_temperature', [theta_level]) w = convert.calc('upward_air_velocity', cubes, levels=lvls) # I think fairly arbitrary cube # z = grid.make_cube(w, 'altitude') # # altitude # # print z # # lvls = ('air_potential_temperature', [theta_level]) # # coord_name, values = lvls # I now need some way to interpolate altitude to desired theta level # z = interpolate.to_level(z, **{coord_name: values}) # z = convert.calc('altitude', iris.cube.CubeList([z]), levels = lvls) glon, glat = grid.get_xy_grids(w) gridpoints = np.array([glon.flatten(), glat.flatten()]).transpose() 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)) tlev_cstrnt = iris.Constraint(air_potential_temperature=theta_level) time_cstrnt = iris.Constraint(time=time) #try this for altitude z = zc.extract(tlev_cstrnt & time_cstrnt) plt.subplot(levels, 2, 2 * kl + 1) plt.contourf(mask, cmap='gray') masked_lon = [] masked_lat = [] alt_list = [] for i, col in enumerate(mask): for j, point in enumerate(col): if point == False: lat = glat[i, j] lon = glon[i, j] alt = z.data[i, j] masked_lon.append(lon) masked_lat.append(lat) alt_list.append(alt) plt.subplot(levels, 2, 2 * kl + 2) plt.scatter(masked_lon, masked_lat, s=2, c='k', marker='.', edgecolor='k') lt = len(masked_lon) points3d = np.zeros([lt, 3]) points3d[:, 0] = np.array(masked_lon) points3d[:, 1] = np.array(masked_lat) points3d[:, 2] = np.array(alt_list) pointsth = np.zeros([lt, 3]) pointsth[:, 0] = np.array(masked_lon) pointsth[:, 1] = np.array(masked_lat) pointsth[:, 2] = theta_level * np.ones([lt]) if kl == 0: outflow_volume = points3d outflow_volume_th = pointsth else: outflow_volume = np.concatenate((outflow_volume, points3d)) outflow_volume_th = np.concatenate((outflow_volume_th, pointsth)) np.save( '/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folder + '/inflow/' + basetime_str + strapp + 'initial_grid.npy', outflow_volume) np.save( '/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folder + '/inflow/' + basetime_str + strapp + 'initial_grid_thlevs.npy', outflow_volume_th) #plt.savefig('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/' + basetime_str + strapp + '_masks.jpg') plt.show()
def random_3D_trajs(k=0, levs=3, theta_0=[320, 325, 310, 310], trajs=50, folder='IOP3/T42', strapp='', var_idxs=[8, 9, 10]): basetime = [ datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12) ] basetime_str = basetime[k].strftime('%Y%m%d_%H') #Tr3 = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble'.format(basetime_str) + strapp) #Tr3 = load('/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble_dPV'.format(basetime_str) + strapp) Tr2 = load('/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folder + '/inflow/{}_3DTrajectoryEnsemble_dPV'.format(basetime_str) + strapp) plt.figure(figsize=(12, 8)) for j, threshs in enumerate([[10, 60], [5, 10], [0, 5], [-60, 0]]): thresh_lo = threshs[0] thresh_hi = threshs[1] Tall = Tr2.select('air_potential_temperature', '!=', -1000) #only those which remain in domain Tasc = Tall.select( 'air_potential_temperature', '>', thresh_lo, time=[Tall.relative_times[0], Tall.relative_times[-1]]) Tasc = Tall.select( 'air_potential_temperature', '<', thresh_hi, time=[Tall.relative_times[0], Tall.relative_times[-1]]) # select all trajectories which ascend at least 10K #plt.subplot(int(levs/2)+1, 2, 1) plt.subplot(2, 2, 1 + j) # for i in xrange(trajs): # i = random.randint(0, len(Tall)-1) # plt.plot(Tall.times, Tall.data[i, :, 5])#3]) for var_idx in var_idxs: Tmean = np.mean(Tasc.data[:, :, var_idx], axis=0) #Tstdev = np.std(Tasc.data[:, :, var_idx], axis=0) plt.plot(Tasc.times, Tmean, linewidth=3, label=Tasc.names[var_idx]) #plt.plot(Tasc.times, Tmean + Tstdev, 'r', linewidth = 1) #plt.plot(Tasc.times, Tmean - Tstdev, 'r', linewidth = 1) #plt.title(folder + '_' + strapp) plt.title('Started at all surfaces, ' + str(thresh_lo) + ' < dtheta < ' + str(thresh_hi)) plt.ylabel('PVU') #theta') plt.legend(loc='upper left') plt.ylim(-.25, .25) pg = plt.gca() fmt = DateFormatter('\n%m/%d') fmt2 = DateFormatter('%H') majorLocator = DayLocator(interval=1) minorLocator = HourLocator(range(0, 24, 6)) pg.xaxis.set_major_formatter(fmt) pg.xaxis.set_minor_formatter(fmt2) pg.xaxis.set_minor_locator(minorLocator) pg.xaxis.set_major_locator(majorLocator) # for j in xrange(levs): # # theta = theta_0[k] + j*5 # # Tt = Tall.select('air_potential_temperature', '>=', theta - 2.5, time = [datetime.timedelta(hours = 0)]) # Tt = Tt.select('air_potential_temperature', '<', theta + 2.5, time = [datetime.timedelta(hours = 0)]) # # those which remain in domain that start on desired theta surface ## Tasc = Tt.select('air_potential_temperature', '>', thresh_lo, time=[Tt.relative_times[0], Tt.relative_times[-1]]) ## Tasc = Tt.select('air_potential_temperature', '<', thresh_hi, time=[Tt.relative_times[0], Tt.relative_times[-1]]) # # select all trajectories which ascend at least 10K # Tasc = Tt # # plt.subplot(int(levs/2)+1, 2, 2+j) # ## for i in xrange(trajs): ## i = random.randint(0, len(Tt)) ## plt.plot(Tasc.times, Tt.data[i, :, 5]) # # for var_idx in var_idxs: # # Tmean = np.mean(Tasc.data[:, :, var_idx], axis = 0) # #Tstdev = np.std(Tasc.data[:, :, var_idx], axis=0) # # plt.plot(Tasc.times, Tmean, linewidth = 3, label = Tasc.names[var_idx]) # #plt.plot(Tasc.times, Tmean + Tstdev, 'r', linewidth = 1) # #plt.plot(Tasc.times, Tmean - Tstdev, 'r', linewidth = 1) # # plt.title('Started at ' + str(theta) + 'K surface') # plt.ylabel('PVU')#theta') # plt.legend() # plt.ylim(-.25, .25) # # pg = plt.gca() # fmt = DateFormatter('\n%m/%d') # fmt2 = DateFormatter('%H') # majorLocator = DayLocator(interval=1) # minorLocator = HourLocator(range(0, 24, 6)) # pg.xaxis.set_major_formatter(fmt) # pg.xaxis.set_minor_formatter(fmt2) # pg.xaxis.set_minor_locator(minorLocator) # pg.xaxis.set_major_locator(majorLocator) #plt.savefig('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/inflow/' + str(trajs) + '_random_3D-trajectories' + strapp + '.png') #plt.savefig('IOP3_T42_random_2x2_50_back.png') plt.savefig( '/home/users/bn826011/NAWDEX/From N Drive/2019_figs/dPV/' + folder[:4] + '_3D_PV_trajectories_all.png') # + str(var_idxs) + strapp + '.png') plt.show()
def plot_ridge_build_IOP6_3D(indiv = False, azm = -60, elv = 40): # produce a 3D animation of the buliding of scandinavian blocking ridge, split into 4 seperate air masses in different colours ascending at different time because it looks cool basetime = datetime.datetime(2016, 9, 30, 12) basetime_str = basetime.strftime('%Y%m%d_%H') TrEnList = [] for k in xrange(4):#5 #TrB = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP6/{}_TrajectoryEnsemble_backward'.format(basetime_str) + str(k)) #TrF = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP6/{}_TrajectoryEnsemble_forward'.format(basetime_str) + str(k)) TrB = load('/storage/silver/scenario/bn826011/WCB_outflow/Final/IOP6/inflow/{}_3DTrajectoryEnsemble'.format(basetime_str) + str(k)) TrF = load('/storage/silver/scenario/bn826011/WCB_outflow/Final/IOP6/inflow/{}_3DTrajectoryEnsemble_fw'.format(basetime_str) + str(k)) TrEn = TrB.__add__(TrF) TrEnList.append(TrEn) tsteps = len(TrEnList[0].times) theta_0 = TrEnList[0].data[0, 0, 2] V = np.linspace(0, 40, 9) # cldt = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/' + basetime_str + # '/prodm_op_gl-mn_' + basetime_str + '_b*_thsfcs_5K.nc', 'total_minus_adv_only_theta') # cldt[-1] = iris.util.new_axis(cldt[-1], 'time') # dtcube = cldt.concatenate_cube() # # create cube of delta theta # clpv = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/' + basetime_str + # '/prodm_op_gl-mn_' + basetime_str + '_c*_thsfcs_5K.nc', 'ertel_potential_vorticity') # clpv[-1] = iris.util.new_axis(clpv[-1], 'time') # pvcube = clpv.concatenate_cube() # and for PV # fig = plt.figure() # ax = fig.gca(projection='3d') scatarray = [] for t in xrange(tsteps): print t scatarray.append([]) fig = plt.figure() ax = fig.gca(projection='3d') #dtheta = dtcube.extract(iris.Constraint(time = TrEnList[0].times[t], air_potential_temperature = theta)) # if t == tsteps-1: # # trop_theta = dtcube.extract(iris.Constraint(time = TrEnList[0].times[t], ertel_potential_vorticity = 2)) # # lon = pvort.coord('longitude').points # lat = pvort.coord('latitude').points # x, y = np.meshgrid(lon, lat) # z = pvort.data # # ax.contour(x, y, z) #colour = [t/tsteps, 1-t/tsteps, .5*(1-t/tsteps)] #colour = [[.5*(t+1)/tsteps, 0, .1*(t+1)/tsteps], [0, 0, (t+1)/tsteps], [.9*(t+1)/tsteps, .5*(t+1)/tsteps, 0], [0, (t+1)/tsteps, 0]] colour = ['Oranges', 'Blues', 'Greys', 'Greens'] hoursuntilstart = [0, 42, 66, 60, 132]#[0, 0, 0, 0, 0] # times at which I want each contour to appear norm = matplotlib.colors.Normalize(-20, 40) for k in xrange(4):#5 tidx = t - hoursuntilstart[k]/6 #adjusted time from start of respective Trajectory Ensemble if tidx >= 0: TrEnindomain = TrEnList[k].select('air_potential_temperature', '>', 275, time = [datetime.timedelta(hours=t*6)]) if TrEnindomain.__len__() != 0: scatarray[t].append(ax.scatter(TrEnindomain.data[:, t, 0]-360, TrEnindomain.data[:, t, 1], TrEnindomain.data[:, t, 2], c = TrEnindomain.data[:, t, 3]-TrEnindomain.data[:, hoursuntilstart[k]/6, 3], marker = '.', edgecolors = 'face', alpha = .5, cmap = colour[k], norm = norm)) ax.set_xlim([-100, 60]) ax.set_ylim([10, 90]) ax.set_zlim([-2000, 14000]) ax.view_init(azim = azm, elev = elv) plt.savefig('/home/users/bn826011/NAWDEX/IOP6_series/all_3D_' + str('{0:02d}'.format(t)) + '_azm' + str(azm) + '.jpg') plt.show() return scatarray
def plot_ridge_build(indiv=False): basetime = datetime.datetime(2016, 9, 30, 12) basetime_str = basetime.strftime('%Y%m%d_%H') TrEnList = [] for k in xrange(5): #4 TrB = load( '/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP6/{}_TrajectoryEnsemble_backward' .format(basetime_str) + str(k)) TrF = load( '/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP6/{}_TrajectoryEnsemble_forward' .format(basetime_str) + str(k)) TrEn = TrB.__add__(TrF) TrEnList.append(TrEn) tsteps = len(TrEnList[0].times) theta_0 = TrEnList[0].data[0, 0, 2] V = np.linspace(0, 40, 9) cldt = iris.load( '/export/cloud/NCASweather/ben/nawdex/mi-ar482/' + basetime_str + '/prodm_op_gl-mn_' + basetime_str + '_b*_thsfcs_5K.nc', 'total_minus_adv_only_theta') cldt[-1] = iris.util.new_axis(cldt[-1], 'time') dtcube = cldt.concatenate_cube() # create cube of delta theta clpv = iris.load( '/export/cloud/NCASweather/ben/nawdex/mi-ar482/' + basetime_str + '/prodm_op_gl-mn_' + basetime_str + '_c*_thsfcs_5K.nc', 'ertel_potential_vorticity') clpv[-1] = iris.util.new_axis(clpv[-1], 'time') pvcube = clpv.concatenate_cube() # and for PV if indiv == False: plt.figure(figsize=(15, 80)) for tht in xrange(3): theta = theta_0 + 5 * tht for t in xrange(tsteps): if indiv == False: plt.subplot(tsteps, 3, t * 3 + tht + 1) else: plt.figure(figsize=(10, 10)) # for plotting individual frames dtheta = dtcube.extract( iris.Constraint(time=TrEnList[0].times[t], air_potential_temperature=theta)) pvort = pvcube.extract( iris.Constraint(time=TrEnList[0].times[t], air_potential_temperature=theta)) iplt.contourf(dtheta, V, cmap='binary') # plot contours of delta theta, gray plt.gca().coastlines(color=[.6, .4, 0]) # plot coastlines dark yellow? iplt.contour(pvort, [2], colors=['k'], linewidths=1.7) # plot 2 PVU contour, black colour = [[.5, 0, .1], 'b', [.9, .5, 0], 'g', [1, 0, 1]] hoursuntilstart = [0, 0, 0, 0, 0] #[0, 42, 66, 0, 132] # times at which I want each contour to appear for k in xrange(5): #4 tidx = t - hoursuntilstart[k] / 6 #adjusted time from start of respective Trajectory Ensemble if tidx >= 0: TrEnindomain = TrEnList[k].select( 'air_potential_temperature', '==', theta, time=[datetime.timedelta(hours=t * 6)]) if TrEnindomain.__len__() != 0: plt.scatter(TrEnindomain.data[:, t, 0] - 360, TrEnindomain.data[:, t, 1], s=2, c=colour[k], marker='.', edgecolor=colour[k]) if indiv == True: plt.savefig( '/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP6/busy_plts/' + basetime_str + '_' + str(int(theta)) + 'K_t=' + str('{0:02d}'.format(t)) + '.png') # for plotting individual frames if t == 0: plt.title(str(theta) + ' K') if tht == 0: timedatenow = TrEnList[0].times[t] plt.text(-90, 70, timedatenow.strftime("%d/%m %HUTC"), rotation='vertical') #label rows with dates and times if indiv == False: pass # plt.savefig('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP6/' + basetime_str + 'fulltraj_all.png')
def compare_filter_size_AB(k=0): datestr = ['0922_12', '0926_12', '0930_12', '0930_12', '0930_12'] thetastart = [6, 9, 6, 6, 6]#8, 9 hoursafterinit = [60, 42, 42, 72, 150]#24, 42 V = np.linspace(-10, 40, 11) filtersize = [40]#[1, 10, 20, 30, 40, 50, 60] fsz = len(filtersize) fig = plt.figure(figsize=(15, 10*fsz + 1))#15 cldt = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/2016' + datestr[k] + '/prodm_op_gl-mn_2016' + datestr[k] + '_b*_thsfcs_5K.nc', 'total_minus_adv_only_theta') # '_c*_thsfcs_5K.nc', 'ertel_potential_vorticity') cldt[-1] = iris.util.new_axis(cldt[-1], 'time') dtcube = cldt.concatenate_cube() # create cube of delta theta clpv = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/2016' + datestr[k] + '/prodm_op_gl-mn_2016' + datestr[k] + '_c*_thsfcs_5K.nc', 'ertel_potential_vorticity') clpv[-1] = iris.util.new_axis(clpv[-1], 'time') pvcube = clpv.concatenate_cube() # create cube of delta theta ################################################# TrB = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP6/2016{}_TrajectoryEnsemble_backward3'.format(datestr[k])) TrF = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP6/2016{}_TrajectoryEnsemble_forward3'.format(datestr[k])) TrEn = TrB.__add__(TrF) start_time = [-1*TrB.relative_times[-1]] ############################################### dtcub = dtcube[hoursafterinit[k]/3, thetastart[k]:thetastart[k]+5] pvcub = pvcube[hoursafterinit[k]/3, thetastart[k]:thetastart[k]+5] for i in xrange(3): for j in xrange(fsz):#7 dt = dtcub.copy()[i] pv = pvcub.copy()[i] #pv.data = filters.median_filter(pv.data, size = filtersize[j]) #dt.data = filters.median_filter(dt.data, size = filtersize[j]) ########################################## trajectories = TrEn.select( 'air_potential_temperature', '==', 280 + 5*(thetastart[k]+i), time = start_time) glon, glat = grid.get_xy_grids(dt) gridpoints = np.array([glon.flatten(), glat.flatten()]).transpose() x = trajectories.x[:, hoursafterinit[k]/6] y = trajectories.y[:, hoursafterinit[k]/6] plt.subplot(5*fsz, 3, 12*j+i+1) plt.scatter(x, y, c = 'k', marker = '.') # Include points within circuit boundary points = np.array([x, y]).transpose() pth = Path(points) print pth ax = fig.add_subplot(5*fsz, 3, 12*j+i+4) patch = patches.PathPatch(pth) ax.add_patch(patch) # Mask all points that are contained in the circuit mask = pth.contains_points(gridpoints).reshape(glat.shape) plt.subplot(5*fsz, 3, 12*j+i+7) plt.contourf(mask) plt.subplot(5*fsz, 3, 12*j+i+10) iplt.contourf(dt, V, cmap = 'seismic', norm = matplotlib.colors.Normalize(-40, 40)) plt.plot(trajectories.data[:, hoursafterinit[k]/6, 0]-360, trajectories.data[:, hoursafterinit[k]/6, 1], color = 'k', marker = '.', ms = .8, mec = 'k', mfc = 'k') dt = dt.copy() #dt.data = np.ma.masked_where(mask, dt.data) dt.data = dt.data - 100*mask #pv = pv.copy() #pv.data = np.ma.masked_where(mask, pv.data) ######################################### # Apply mask to the data # Have made decision to apply mask before and after filtering # and instead of traditional mask, trying to take 100 off affected areas instead pv.data = filters.median_filter(pv.data, size = filtersize[j]) dt.data = filters.median_filter(dt.data, size = filtersize[j]) dt = dt.copy() dt.data = dt.data - 100*mask plt.subplot(5*fsz, 3, 6*j+i+13)#7 iplt.contourf(dt, V, cmap = 'seismic', norm = matplotlib.colors.Normalize(-40, 40)) iplt.contour(pv, [PVU], colors = ['m']) iplt.contour(dt, [0], colors = ['g']) criteria = np.logical_and(pv.data < 2, dt.data > 0) # from Leo's code pv.data = criteria.astype(int) cs = iplt.contour(pv, [0.5], colors = ['k']) # additional requirement of pv < 2 on contour if j == 0: potemp = dtcube.coord('air_potential_temperature') plt.title(str(potemp.points[thetastart[k]+i]) + ' K') #label columns with isentropic levels if i == 0: plt.text(-90, 70, 'filter size = ' + str(filtersize[j]), rotation = 'vertical') #label rows with filter size reftime = datetime.datetime(1970, 1, 1) hourssince = dtcub.coord('time').points[0] timedatenow = reftime + datetime.timedelta(hours = hourssince) plt.savefig('2016' + timedatenow.strftime("%d%m_%H") + '_delta_theta_' + str(PVU) + 'PVU_outflow__dtfilter_5.jpg')
def outflow_AB(k=0, thlevs = 3, thetastart = [6, 9, 6, 6, 6, 6], hoursafterinit = [60, 42, 42, 72, 96, 108], filtersize = 30, resolution = 0.05, masks = 1, folder = 'IOP3/ABsplit', strapp = ''): "Returns numpy array of indices on contour around WCB outflow" "k is an index for case, of 0, 1, 2, 3, 4, 5" "thlevs is the number of isentropic levels considered" "thetastart is an array of four initial isentropic levels considered" "isentropic level = 280 + thetastart*5" "filtersize is size for median filter" "resolution is minimum L2 distance between two points on returned contour" datestr = ['0922_12', '0926_12', '0930_12', '0930_12', '0930_12', '0930_12', '0930_12'] #hoursafterinit = [60, 42, 42, 72, 96, 96]# 42 for all 21, 18 # start time in hours after first time in dataset #filtersize = [30, 30, 30, 30, 20, 35], the 20 & 35 to deal with #two separate outflows incredibly close together cldt = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/2016' + datestr[k] + '/prodm_op_gl-mn_2016' + datestr[k] + '_b*_thsfcs_5K.nc', 'total_minus_adv_only_theta') cldt[-1] = iris.util.new_axis(cldt[-1], 'time') dtcube = cldt.concatenate_cube() # create cube of delta theta clpv = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/2016' + datestr[k] + '/prodm_op_gl-mn_2016' + datestr[k] + '_c*_thsfcs_5K.nc', 'ertel_potential_vorticity') clpv[-1] = iris.util.new_axis(clpv[-1], 'time') pvcube = clpv.concatenate_cube() # and for PV ################################################# TrEn = [] start_time = [] if k == 6: rg = [3] else: rg = xrange(masks) for TE in rg: TrB = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/2016{}_TrajectoryEnsemble_backward'.format(datestr[k]) + str(TE)) TrF = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/2016{}_TrajectoryEnsemble_forward'.format(datestr[k]) + str(TE)) TrEn.append(TrB.__add__(TrF)) start_time.append([-1*TrB.relative_times[-1]]) ############################################### # for labelling potemp = dtcube.coord('air_potential_temperature') reftime = datetime.datetime(1970, 1, 1) hourssince = dtcube.coord('time').points[hoursafterinit[k]/3] timedatenow = reftime + datetime.timedelta(hours = hourssince) # for labelling plt.figure(figsize = (10, 14)) V = np.linspace(-10, 40, 11) outflow_volume = np.array([]) for i in xrange(thlevs): cutoff = 250 endoff = -1 filtersize_t, filtersize_p = filtersize, filtersize if k == 3: cutoff = 50 endoff = -50 if k == 4: #3rd outflow into IOP6 cutoff = 200 filtersize_p = 20 #Pv division filtersize_t = 20 #narrow feature anyway if k == 5: #outflow into IOP7, bit of a weird one cutoff = 0 endoff = -150 filtersize_p = 5 #to maintain very fine PV structure dividing the ridges if k == 6: #why am I doing another outflow into IOP7?!! cutoff = 150 dtcub = dtcube[hoursafterinit[k]/3, thetastart[k]+i, :, cutoff:endoff].copy() #restrict to outflow time and selected theta level #the cutoff artificially truncates the domain s.t. only the region we want is found #removes West: can't see new developing storms pvcub = pvcube[hoursafterinit[k]/3, thetastart[k]+i, :, cutoff:endoff].copy() #restrict to outflow time and selected theta level #the 150 artificially truncates the domain s.t. only the region we want is found ########################################## mask = [] for TE in xrange(masks): trajectories = TrEn[TE].select( 'air_potential_temperature', '==', 280 + 5*(thetastart[k]+i), time = start_time[TE]) # 'air_potential_temperature', '==', 280 + 5*(thetastart[k]+i), time = [datetime.timedelta(hours=hoursafterinit[k])]) # option for if points which have left the domain are a problem, but it probably won't help glon, glat = grid.get_xy_grids(dtcub) gridpoints = np.array([glon.flatten(), glat.flatten()]).transpose() x = trajectories.x[:, hoursafterinit[k]/6] y = trajectories.y[:, hoursafterinit[k]/6] # Include points within circuit boundary points = np.array([x, y]).transpose() pth = Path(points) # Mask all points that are contained in the circuit mask.append(pth.contains_points(gridpoints).reshape(glat.shape)) dtcub = dtcub.copy() dtcub.data = dtcub.data - 100*mask[TE] ######################################### # remove sections covered by previous outflow dtcub.data = filters.median_filter(dtcub.data, size = filtersize_t) #apply median filter to smooth field pvcub.data = filters.median_filter(pvcub.data, size = filtersize_p) #apply median filter to smooth field for TE in xrange(masks): dtcub.data = dtcub.data - 100*mask[TE] # remove mask before and after to ensure no overlap plt.subplot(thlevs, 2, 2*i+1) iplt.contourf(dtcub, V, cmap = 'seismic', norm = matplotlib.colors.Normalize(-40, 40)) plt.text(-90, 70, timedatenow.strftime("%m%d_%H") + '_' + str(int(potemp.points[thetastart[k]+i])) + 'K', rotation = 'vertical') plt.gca().coastlines(color = [.8, .9, .8]) iplt.contour(pvcub, [2], colours = ['k']) criteria = np.logical_and(pvcub.data < 2, dtcub.data > 0) # from Leo's code pvcub.data = criteria.astype(int) cs = iplt.contour(pvcub, [0.5], colors = ['g']) # additional requirement of pv < 2 on contour contours = trop.get_contour_verts(cs) # returns array of arrays of vertices for zero contours ncon = np.size(contours[0]) #number of contours lencon = np.zeros(ncon) # empty array of lengths of contorus (in lat/long space) for j in xrange(ncon): lencon[j] = len_con(contours[0][j]) imax = lencon.argmax() len_max = lencon[imax] # index of longest contour lcontour = contours[0][imax] # longest contour confail = False while not(trop.is_closed_contour(lcontour)): #Still need to check is_closed_contour works right lencon = np.delete(lencon, imax) del contours[0][imax] # this contour is not closed, remove & find the next one if np.size(lencon) == 0: confail = True # indicator that finding contour has failed break else: imax = lencon.argmax() len_max = lencon[imax] # new index of longest contour lcontour = contours[0][imax] # new longest contour plt.subplot(thlevs, 2, 2*i+2) iplt.contourf(dtcube[hoursafterinit[k]/3, thetastart[k]+i], V, cmap = 'seismic', norm = matplotlib.colors.Normalize(-40, 40)) t = hoursafterinit[k]/6 theta = (thetastart[k] + i)*5 + 280 for TE in xrange(masks): TrEnindomain = TrEn[TE].select('air_potential_temperature', '==', theta, time = [datetime.timedelta(hours=6*t)]) plt.plot(TrEnindomain.data[:, t, 0]-360, TrEnindomain.data[:, t, 1], color = [.8, .8, .8], marker = '.', ms = .8, mec = [.4, .4, .4], mfc = [.4, .4, .4]) if confail == False: points = increase_nodes(lcontour, resolution) # increase number of points on the contour such that they have minimum spacing resolution plt.plot(points[:, 0]-360, points[:, 1], marker = '.', ms = 1, mec = 'k', mfc = 'k') points3d = np.zeros([points.shape[0], 3]) points3d[:, 0:2] = points points3d[:, 2] = potemp.points[thetastart[k]+i] if i == 0: outflow_volume = points3d else: outflow_volume = np.concatenate((outflow_volume, points3d)) else: plt.title('Unable to find contour around outflow at this level') #IOP = [3, 5, 6] np.save('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/' + timedatenow.strftime("%m%d_%H") + strapp + '.npy', outflow_volume) plt.savefig('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/' + timedatenow.strftime("%m%d_%H") + strapp + '_image.jpg') plt.show() return
def out_ridge_mass(k = 0, levs = 3, thetastart = [8, 9, 6, 6], hoursafterinit = [42, 36, 42, 24], filtersize = 5, dtheta = 1, folder = 'IOP3/T42', strapp = ''): basetime = [datetime.datetime(2016, 9, 22, 12), datetime.datetime(2016, 9, 26, 12), datetime.datetime(2016, 9, 30, 12), datetime.datetime(2016, 10, 03, 12)] basetime_str = basetime[k].strftime('%Y%m%d_%H') datadir = '/export/cloud/NCASweather/ben/nawdex/mi-ar482/{}/'.format(basetime_str) #eqlat = [0, 0, 0, 0, 0, 0, 55, 50, 47, 43, 38, 36] # equivalent latitude indexed on theta level, for November eqlat = [0, 0, 0, 0, 0, 0, 55, 51, 48, 45, 42, 40] # a guess at equivalent latitude for September, because who knows TrB = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/' + folder + '/{}_TrajectoryEnsemble_backward'.format(basetime_str) + strapp) theta_0 = TrB.data[0, 0, 2] ridge_mass = np.zeros(levs) for tht in xrange(levs): theta = theta_0 + 5*tht TrEntheta = TrB.select('air_potential_temperature', '==', theta, time = [datetime.timedelta(hours = 0)]) # This gives the levels at the designated start time mapping = {} for t in TrEntheta.times: leadtimehr = np.int((t - basetime[k]).total_seconds()) / 3600 fn = 'prodm_op_gl-mn_{0}_d{1:03d}_thgrid.pp'.\ format(basetime_str, 12 * (leadtimehr / 12)) mapping[t] = datadir + fn fcast = forecast.Forecast(basetime[k], mapping) time = TrB.times[0] t = 0 cubelist = fcast.set_time(time) cubes = cubelist.extract(iris.Constraint(time = time)) levels = ('air_potential_temperature', [theta]) # Load grid parameters example_cube = convert.calc('upward_air_velocity', cubes, levels=levels) # Create a 1d array of points for determining which gridpoints are # contained in the trajectory circuit when performing volume # integrals glon, glat = grid.get_xy_grids(example_cube) gridpoints = np.array([glon.flatten(), glat.flatten()]).transpose() # JB to do integrals need dlambda, dphi, not always 0.11 dlon = np.diff(glon) if np.diff(dlon).any(): print 'longitudinal spacing not uniform' # there exists a non-zero difference between longitude spacings else: dlambda = dlon[0][0] #as they are all the same dlat = np.diff(glat.transpose()) if np.diff(dlat).any(): print 'latitudinal spacing not uniform' # there exists a non-zero difference between latitude spacings else: dphi = dlat[0][0] #as they are all the same x = TrEntheta.x[:, t] y = TrEntheta.y[:, t] thtst = [0, 0, 0, 0] thtst[k] += tht + thetastart[k] ridge_area, pv = find_ridge(k = k, thlevs = 1, thetastart = thtst, hoursafterinit = hoursafterinit, filtersize = filtersize, eqlat = eqlat[thetastart[k]+tht], savet = False, folder = folder, strapp = strapp) xr = np.array(ridge_area[:, 0]) yr = np.array(ridge_area[:, 1]) ridge_mass[tht] = mass_integrals(cubes, xr, yr, glat, gridpoints, theta, dtheta, dlambda, dphi)[2].data iplt.contour(pv, [2], colours = ['m']) plt.plot(xr-360, yr, color = [.4, .4, .4], marker = '.', mec = 'k', mfc = 'k') plt.plot(x-360, y, color = [.4, .4, 1], marker = '.', mec = 'b', mfc = 'b') plt.gca().coastlines(color = [.6, .4, 0]) plt.savefig('easy_to_find/' + folder + '_ridge_' + str(theta) + 'K_Nov.png') plt.show() np.save('easy_to_find/' + folder + strapp + '_ridge_mass.np', ridge_mass) return ridge_mass
def plot_ridge_IOP3(indiv = False): basetime = datetime.datetime(2016, 9, 22, 12) basetime_str = basetime.strftime('%Y%m%d_%H') TrEnList = [] for k in xrange(2): TrB = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP3/ABsplit/{}_TrajectoryEnsemble_backward'.format(basetime_str) + str(k)) TrF = load('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP3/ABsplit/{}_TrajectoryEnsemble_forward'.format(basetime_str) + str(k)) TrEn = TrB.__add__(TrF) TrEnList.append(TrEn) tsteps = len(TrEnList[0].times) theta_0 = TrEnList[0].data[0, 0, 2] V = np.linspace(-10, 40, 11) cldt = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/' + basetime_str + '/prodm_op_gl-mn_' + basetime_str + '_b*_thsfcs_5K.nc', 'total_minus_adv_only_theta') cldt[-1] = iris.util.new_axis(cldt[-1], 'time') dtcube = cldt.concatenate_cube() # create cube of delta theta clpv = iris.load('/export/cloud/NCASweather/ben/nawdex/mi-ar482/' + basetime_str + '/prodm_op_gl-mn_' + basetime_str + '_c*_thsfcs_5K.nc', 'ertel_potential_vorticity') clpv[-1] = iris.util.new_axis(clpv[-1], 'time') pvcube = clpv.concatenate_cube() # and for PV if indiv == False: plt.figure(figsize = (25, 40)) for tht in xrange(5): theta = theta_0 + 5*tht for t in xrange(tsteps): if indiv == False: plt.subplot(tsteps, 5, t*5 + tht + 1) else: plt.figure(figsize = (10, 10)) # plot frames individually dtheta = dtcube.extract(iris.Constraint(time = TrEnList[0].times[t], air_potential_temperature = theta)) pvort = pvcube.extract(iris.Constraint(time = TrEnList[0].times[t], air_potential_temperature = theta)) iplt.contourf(dtheta, V, cmap = 'seismic', norm = matplotlib.colors.Normalize(-40, 40)) # plot contours of delta theta plt.gca().coastlines(color = [.6, .4, 0]) # plot coastlines dark yellow? iplt.contour(pvort, [2], colors = ['m']) #, linewidths = 1.7) # plot 2 PVU contour, pink colour = [[0, .8, 0], 'k'] hoursuntilstart = [0, 30] for k in xrange(2): if k == 1 and tht == 0: pass # second contour not sensible on lowest theta level else: tidx = t - hoursuntilstart[k]/6 #adjusted time from start of respective Trajectory Ensemble if tidx >= 0: TrEnindomain = TrEnList[k].select('air_potential_temperature', '==', theta, time = [datetime.timedelta(hours=t*6)]) # changed tidx to t as I actually started both ensembles from t = 0, but still don't want the mess of outflow B in the first 24 hours if TrEnindomain.__len__() != 0: plt.plot(TrEnindomain.data[:, t, 0]-360, TrEnindomain.data[:, t, 1], color = colour[k], marker = '.', ms = .8, mec = colour[k], mfc = colour[k]) if indiv == True: plt.savefig('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP3/ABsplit/indv_plts/' + basetime_str + '_' + str(int(theta)) + 'K_t=' + str('{0:02d}'.format(t)) + '.png') # save individual frames if t == 0: plt.title(str(theta) + ' K') if tht == 0: timedatenow = TrEnList[0].times[t] plt.text(-90, 70, timedatenow.strftime("%d/%m %HUTC"), rotation = 'vertical') #label rows with dates and times if indiv == False: plt.savefig('/glusterfs/msc/users_2018/bn826011/NAWDEX/Final/IOP3/ABsplit/' + basetime_str + 'fulltraj_split.png')
def PV_along_trajectories(folder='IOP3/T42', time_string='20160922_12', name='', theta_min=24, no_of_trajs=10, plotnotmean=True): TrEn = load('/storage/silver/scenario/bn826011/WCB_outflow/Final/' + folder + '/inflow/' + time_string + '_3DTrajectoryEnsemble_new' + name) # load arbitrary set of 3D trajectories times = TrEn.times # get array containing pertinent times clpv = iris.load( '/storage/silver/NCAS-Weather/ben/nawdex/mi-ar482/' + time_string + '/prodm_op_gl-mn_' + time_string + '_c*_thsfcs.nc', 'ertel_potential_vorticity') clpv[-1] = iris.util.new_axis(clpv[-1], 'time') pvcube = clpv.concatenate_cube() # load full 3D PV fields for corresponding case # could restrict this to pertinent times to save processing time cldt = iris.load('/storage/silver/NCAS-Weather/ben/nawdex/mi-ar482/' + time_string + '/prodm_op_gl-mn_' + time_string + '_b*_thsfcs.nc', 'total_minus_adv_only_theta' ) # '_c*_thsfcs_5K.nc', 'ertel_potential_vorticity') cldt[-1] = iris.util.new_axis(cldt[-1], 'time') dtcube = cldt.concatenate_cube() # same for diabatic heating proxy delta_lat = np.mean(np.diff(pvcube.coord('latitude').points[:10])) / 2 # spacing of latitude grid delta_lon = np.mean(np.diff(pvcube.coord('longitude').points[:10])) / 2 # spacing of longitude grid trajectory_bin = [] for traj in TrEn: if abs(traj.data[0, 3] - traj.data[-1, 3]) > theta_min and min( traj.data[:, 3]) > 300: trajectory_bin.append(traj) # make a list of trajectories which ascend the most # NOTE: the data I have for some reason only goes down to 300K - possible drawback n = int(max(np.floor(len(trajectory_bin) / no_of_trajs), 1)) # interval of selection based on desired number of trajectories for figno, trajex in enumerate(trajectory_bin[::n]): lat = trajex.data[:, 1] lon = trajex.data[:, 0] theta = trajex.data[:, 3] pvs = [] dts = [] for i in range(len(times)): lat_constraint = iris.Constraint(latitude=lambda cell: lat[ i] - delta_lat < cell < lat[i] + delta_lat) lon_constraint = iris.Constraint(longitude=lambda cell: lon[ i] - delta_lon < cell < lon[i] + delta_lon) time_constraint = iris.Constraint(time=times[i]) pvs.append( pvcube.extract(lat_constraint & lon_constraint & time_constraint)) dts.append( dtcube.extract(lat_constraint & lon_constraint & time_constraint)) ### hack fix for points not being found ncl = [] tcl = [] try: for cube in pvs: if cube.ndim == 1: ncl.append(cube) elif cube.ndim == 2: ncl.append(cube[:, 0]) else: ncl.append(cube[:, 0, 0]) ### hack fix for points not being found for cube in dts: if cube.ndim == 1: tcl.append(cube) elif cube.ndim == 2: tcl.append(cube[:, 0]) else: tcl.append(cube[:, 0, 0]) ### hack fix for points not being found pvtrajcubes = iris.cube.CubeList(ncl) dttrajcubes = iris.cube.CubeList(tcl) pvmerge = pvtrajcubes.merge_cube() dtmerge = dttrajcubes.merge_cube() if plotnotmean: plt.figure(figsize=(12, 12)) plt.subplot(2, 2, 1) qplt.contourf(pvmerge, np.linspace(-3, 3, 25), cmap='RdBu_r') plt.plot(times, theta) plt.subplot(2, 2, 2) qplt.contourf(dtmerge, np.linspace(-25, 25, 26), cmap='RdBu_r') plt.plot(times, theta) plt.subplot(2, 1, 2) qplt.contour(pvcube[14, 10], [2]) plt.gca().coastlines() plt.plot(lon - 360, lat, linewidth=3) plt.savefig('PV_dtheta_trajectory_crosssection_' + str(figno) + '_' + time_string + '.png') plt.show() except AttributeError as e: print e else: if figno == 0: pvarray = np.array([pvmerge.data]) dtarray = np.array([dtmerge.data]) thetarray = np.array([theta]) # for the first profile, initialise a numpy array else: pvarray = np.append(pvarray, [pvmerge.data], axis=0) dtarray = np.append(dtarray, [dtmerge.data], axis=0) thetarray = np.append(thetarray, [theta], axis=0) if not plotnotmean: lts = len(times) pvmean = np.mean(pvarray, axis=0) dtmean = np.mean(dtarray, axis=0) thetamean = np.mean(thetarray, axis=0) # create mean fields along trajectories ytheta = np.repeat([np.linspace(300, 340, 17)], lts, axis=0) xtime = np.repeat([np.linspace(0, (lts - 1) * 6, lts)], 17, axis=0).T # create arrays for axes plt.figure(figsize=(12, 8)) plt.subplot(1, 2, 1) plt.contourf(xtime, ytheta, pvmean, np.linspace(-3, 3, 25), cmap='RdBu_r') plt.plot(np.linspace((lts - 1) * 6, 0, lts), thetamean) plt.title('Average PV along trajectory for > 20K ascent') plt.xlabel('time from start, hours') plt.ylabel('theta, kelvin') plt.subplot(1, 2, 2) plt.contourf(xtime, ytheta, dtmean, np.linspace(-25, 25, 26), cmap='RdBu_r') plt.plot(np.linspace((lts - 1) * 6, 0, lts), thetamean) plt.title('Average diabatic heating') plt.xlabel('time, hours') plt.savefig('PV_dtheta_trajectory_crosssection_mean_' + time_string + '.png') plt.show()