def side_patches(elements, lat_max, lon0, data): # Get SideElements interpolated to lon0 selements = fesom_sidegrid(elements, data, lon0, lat_max) # Build an array of quadrilateral patches for the plot, and of data # values corresponding to each SideElement patches = [] values = [] lat_min = lat_max for selm in selements: # Make patch coord = transpose(vstack((selm.y, selm.z))) patches.append(Polygon(coord, True, linewidth=0.)) # Save data value values.append(selm.var) lat_min = min(lat_min, amin(selm.y)) # Show a little bit of the land mask lat_min = lat_min - 0.5 return patches, values, lat_min
def zonal_ts_before_after_ross_2094(): # File paths mesh_path = '/short/y99/kaa561/FESOM/mesh/meshB/' file_beg = '/short/y99/kaa561/FESOM/highres_spinup/annual_avg.oce.mean.1996.2005.nc' file_end = '/short/y99/kaa561/FESOM/rcp85_A/output/MK44005.2094.oce.mean.nc' lon0 = -159 lat_min = -85 lat_max = -73 print 'Building FESOM mesh' elm2D = fesom_grid(mesh_path) print 'Reading temperature and salinity data' id = Dataset(file_beg, 'r') temp_nodes_beg = id.variables['temp'][0, :] salt_nodes_beg = id.variables['salt'][0, :] id.close() # Annually average 2094 id = Dataset(file_end, 'r') temp_nodes_end = mean(id.variables['temp'][:, :], axis=0) salt_nodes_end = mean(id.variables['salt'][:, :], axis=0) id.close() print 'Interpolating to ' + str(lon0) # Build arrays of SideElements making up zonal slices # Start with beginning selements_temp_beg = fesom_sidegrid(elm2D, temp_nodes_beg, lon0, lat_max) selements_salt_beg = fesom_sidegrid(elm2D, salt_nodes_beg, lon0, lat_max) # Build array of quadrilateral patches for the plots, and data values # corresponding to each SideElement patches = [] temp_beg = [] for selm in selements_temp_beg: # Make patch coord = transpose(vstack((selm.y, selm.z))) patches.append(Polygon(coord, True, linewidth=0.)) # Save data value temp_beg.append(selm.var) temp_beg = array(temp_beg) # Salinity has same patches but different values salt_beg = [] for selm in selements_salt_beg: salt_beg.append(selm.var) salt_beg = array(salt_beg) # Repeat for end selements_temp_end = fesom_sidegrid(elm2D, temp_nodes_end, lon0, lat_max) selements_salt_end = fesom_sidegrid(elm2D, salt_nodes_end, lon0, lat_max) temp_end = [] for selm in selements_temp_end: temp_end.append(selm.var) temp_end = array(temp_end) salt_end = [] for selm in selements_salt_end: salt_end.append(selm.var) salt_end = array(salt_end) # Find bounds on each variable temp_min = min(amin(temp_beg), amin(temp_end)) temp_max = max(amax(temp_beg), amax(temp_end)) salt_min = min(amin(salt_beg), amin(salt_end)) salt_max = max(amax(salt_beg), amax(salt_end)) # Find deepest depth # Start with 0 depth_min = 0 # Modify with patches for selm in selements_temp_beg: depth_min = min(depth_min, amin(selm.z)) # Round down to nearest 50 metres depth_min = floor(depth_min / 50) * 50 print 'Plotting' fig = figure(figsize=(16, 10)) # Temperature gs_temp = GridSpec(1, 2) gs_temp.update(left=0.11, right=0.9, bottom=0.5, top=0.9, wspace=0.05, hspace=0.5) # Beginning ax = subplot(gs_temp[0, 0]) img = PatchCollection(patches, cmap='jet') img.set_array(temp_beg) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title(r'Temperature ($^{\circ}$C), 1996-2005', fontsize=24) ax.set_xticklabels([]) ylabel('Depth (m)', fontsize=18) # End ax = subplot(gs_temp[0, 1]) img = PatchCollection(patches, cmap='jet') img.set_array(temp_end) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title(r'Temperature ($^{\circ}$C), 2094', fontsize=24) ax.set_xticklabels([]) ax.set_yticklabels([]) # Add a colorbar on the right cbaxes = fig.add_axes([0.92, 0.55, 0.02, 0.3]) cbar = colorbar(img, cax=cbaxes, extend='both') cbar.ax.tick_params(labelsize=16) # Salinity gs_salt = GridSpec(1, 2) gs_salt.update(left=0.11, right=0.9, bottom=0.05, top=0.45, wspace=0.05, hspace=0.5) # Beginning ax = subplot(gs_salt[0, 0]) img = PatchCollection(patches, cmap='jet') img.set_array(salt_beg) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title('Salinity (psu), 1996-2005', fontsize=24) xlabel('Latitude', fontsize=18) ylabel('Depth (m)', fontsize=18) # End ax = subplot(gs_salt[0, 1]) img = PatchCollection(patches, cmap='jet') img.set_array(salt_end) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title('Salinity (psu), 2094', fontsize=24) xlabel('Latitude', fontsize=18) ax.set_yticklabels([]) # Add a colorbar on the right cbaxes = fig.add_axes([0.92, 0.1, 0.02, 0.3]) cbar = colorbar(img, cax=cbaxes, extend='both') cbar.ax.tick_params(labelsize=16) # Main title suptitle(r'RCP 8.5 A, 159$^{\circ}$W', fontsize=28) fig.show() fig.savefig('159W_rcp85_A_2094.png')
def temp_salt_slice (elm2D, file_path, tstep, lon0, depth_min, save=False, fig_name=None): # Set northern boundary and upper (surface) boundary lat_max = -30 depth_max = 0 # Bounds on colour scales for temperature and salinity var_min = [-2, 33.8] var_max = [3, 34.8] var_tick = [1, 0.2] # Read temperature and salinity at each node id = Dataset(file_path, 'r') temp = id.variables['temp'][tstep-1,:] salt = id.variables['salt'][tstep-1,:] id.close() # Choose what to write on the title about longitude if lon0 < 0: lon_string = str(-lon0) + 'W' else: lon_string = str(lon0) + 'E' # Set up plots fig = figure(figsize=(24,6)) # Make SideElements with temperature data selements_temp = fesom_sidegrid(elm2D, temp, lon0, lat_max) # Build an array of quadrilateral patches for the plot, and of data values # corresponding to each SideElement # Also find the minimum latitude of any SideElement patches = [] values = [] lat_min = lat_max for selm in selements_temp: # Make patch coord = transpose(vstack((selm.y,selm.z))) patches.append(Polygon(coord, True, linewidth=0.)) # Save data value values.append(selm.var) # Update minimum latitude if needed lat_min = min(lat_min, amin(selm.y)) # Set southern boundary to be just south of the minimum latitude lat_min = lat_min-1 # Add to plot ax1 = fig.add_subplot(1,2,1) img1 = PatchCollection(patches) img1.set_array(array(values)) img1.set_edgecolor('face') img1.set_clim(vmin=var_min[0], vmax=var_max[0]) ax1.add_collection(img1) xlim(lat_min, lat_max) ylim(depth_min, depth_max) xlabel('Latitude') ylabel('Depth (m)') title(r'Temperature ($^{\circ}$C)', fontsize=20) cbar1 = colorbar(img1, ticks=arange(var_min[0], var_max[0]+var_tick[0], var_tick[0]), extend='both') cbar1.ax.tick_params(labelsize=16) # Repeat for salinity selements_salt = fesom_sidegrid(elm2D, salt, lon0, lat_max) patches = [] values = [] for selm in selements_salt: coord = transpose(vstack((selm.y,selm.z))) patches.append(Polygon(coord, True, linewidth=0.)) values.append(selm.var) ax2 = fig.add_subplot(1,2,2) img2 = PatchCollection(patches) img2.set_array(array(values)) img2.set_edgecolor('face') img2.set_clim(vmin=var_min[1], vmax=var_max[1]) ax2.add_collection(img2) xlim(lat_min, lat_max) ylim(depth_min, depth_max) xlabel('Latitude') ylabel('Depth (m)') title('Salinity (psu)', fontsize=20) cbar2 = colorbar(img2, ticks=arange(var_min[1], var_max[1]+var_tick[1], var_tick[1]), extend='both') cbar2.ax.tick_params(labelsize=16) suptitle('Time index ' + str(tstep) + ', ' + lon_string, fontsize=24) subplots_adjust(wspace=0.025) if save: fig.savefig(fig_name) else: fig.show()
def zonal_cavity_ts_res(): # Paths to mesh directories mesh_path_low = '../FESOM/mesh/low_res/' mesh_path_high = '../FESOM/mesh/high_res/' # Paths to output files output_path_low = '../FESOM/lowres_spinup/rep3/' output_path_high = '../FESOM/highres_spinup/rep3/' file_name = 'annual_avg.oce.mean.nc' # Name of each ice shelf shelf_names = [ 'Larsen D Ice Shelf', 'Larsen C Ice Shelf', 'Wilkins & George VI & Stange Ice Shelves', 'Ronne-Filchner Ice Shelf', 'Abbot Ice Shelf', 'Pine Island Glacier Ice Shelf', 'Thwaites Ice Shelf', 'Dotson Ice Shelf', 'Getz Ice Shelf', 'Nickerson Ice Shelf', 'Sulzberger Ice Shelf', 'Mertz Ice Shelf', 'Totten & Moscow University Ice Shelves', 'Shackleton Ice Shelf', 'West Ice Shelf', 'Amery Ice Shelf', 'Prince Harald Ice Shelf', 'Baudouin & Borchgrevink Ice Shelves', 'Lazarev Ice Shelf', 'Nivl Ice Shelf', 'Fimbul & Jelbart & Ekstrom Ice Shelves', 'Brunt & Riiser-Larsen Ice Shelves', 'Ross Ice Shelf' ] # Beginnings of filenames for figures fig_heads = [ 'larsen_d', 'larsen_c', 'wilkins_georgevi_stange', 'ronne_filchner', 'abbot', 'pig', 'thwaites', 'dotson', 'getz', 'nickerson', 'sulzberger', 'mertz', 'totten_moscowuni', 'shackleton', 'west', 'amery', 'prince_harald', 'baudouin_borchgrevink', 'lazarev', 'nivl', 'fimbul_jelbart_ekstrom', 'brunt_riiser_larsen', 'ross' ] # Longitudes intersecting each ice shelf lon0 = [ -60, -62, -68, -55, -93, -101, -106, -113, -120, -145, -150, 145, 116, 96, 85, 71, 36, 25, 15, 11, -1, -20, 180 ] # Latitude bounds for each ice shelf lat_min = [ -73.1, -69.35, -73.1, -82.6, -73.28, -75.4, -75.5, -75, -74.9, -75.9, -77.8, -67.7, -67.17, -66.67, -67.25, -72, -69.7, -71, -70.4, -70.75, -71.83, -75.6, -84.6 ] lat_max = [ -72, -66.13, -70, -75.5, -72.3, -74.4, -74.67, -74, -73.5, -75.3, -76.41, -67, -66.5, -64.83, -66.25, -68.5, -68.7, -69.9, -69.33, -69.83, -69.33, -72.9, -77 ] num_shelves = len(shelf_names) print 'Building FESOM mesh' elm2D_low = fesom_grid(mesh_path_low) elm2D_high = fesom_grid(mesh_path_high) print 'Reading temperature and salinity data' id = Dataset(output_path_low + file_name, 'r') temp_nodes_low = id.variables['temp'][0, :] salt_nodes_low = id.variables['salt'][0, :] id.close() id = Dataset(output_path_high + file_name, 'r') temp_nodes_high = id.variables['temp'][0, :] salt_nodes_high = id.variables['salt'][0, :] id.close() # Loop over ice shelves for index in range(num_shelves): print 'Processing ' + shelf_names[index] # Figure out what to write on the title about longitude if lon0[index] < 0: lon_string = ' (' + str(-lon0[index]) + r'$^{\circ}$W)' else: lon_string = ' (' + str(lon0[index]) + r'$^{\circ}$E)' # Build arrays of SideElements making up zonal slices selements_temp_low = fesom_sidegrid(elm2D_low, temp_nodes_low, lon0[index], lat_max[index]) selements_salt_low = fesom_sidegrid(elm2D_low, salt_nodes_low, lon0[index], lat_max[index]) selements_temp_high = fesom_sidegrid(elm2D_high, temp_nodes_high, lon0[index], lat_max[index]) selements_salt_high = fesom_sidegrid(elm2D_high, salt_nodes_high, lon0[index], lat_max[index]) # Build array of quadrilateral patches for the plots, and data values # corresponding to each SideElement patches_low = [] temp_low = [] for selm in selements_temp_low: # Make patch coord = transpose(vstack((selm.y, selm.z))) patches_low.append(Polygon(coord, True, linewidth=0.)) # Save data value temp_low.append(selm.var) temp_low = array(temp_low) # Salinity has same patches but different values salt_low = [] for selm in selements_salt_low: salt_low.append(selm.var) salt_low = array(salt_low) # Repeat for high-res patches_high = [] temp_high = [] for selm in selements_temp_high: coord = transpose(vstack((selm.y, selm.z))) patches_high.append(Polygon(coord, True, linewidth=0.)) temp_high.append(selm.var) temp_high = array(temp_high) salt_high = [] for selm in selements_salt_high: salt_high.append(selm.var) salt_high = array(salt_high) # Find bounds on each variable temp_min = min(amin(temp_low), amin(temp_high)) temp_max = max(amax(temp_low), amax(temp_high)) salt_min = min(amin(salt_low), amin(salt_high)) salt_max = max(amax(salt_low), amax(salt_high)) # Find deepest depth # Start with 0 depth_min = 0 # Modify with low-res patches for selm in selements_temp_low: depth_min = min(depth_min, amin(selm.z)) # Modify with high-res patches for selm in selements_temp_high: depth_min = min(depth_min, amin(selm.z)) # Round down to nearest 50 metres depth_min = floor(depth_min / 50) * 50 # Plot fig = figure(figsize=(18, 12)) # Low-res temperature ax = fig.add_subplot(2, 2, 1) img1 = PatchCollection(patches_low, cmap='jet') img1.set_array(temp_low) img1.set_edgecolor('face') img1.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img1) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) title(r'Low-res temperature ($^{\circ}$C)', fontsize=20) ylabel('Depth (m)', fontsize=16) # High-res temperature ax = fig.add_subplot(2, 2, 2) img2 = PatchCollection(patches_high, cmap='jet') img2.set_array(temp_high) img2.set_edgecolor('face') img2.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img2) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) title(r'High-res temperature ($^{\circ}$C)', fontsize=20) # Add colorbar for temperature cbaxes_temp = fig.add_axes([0.92, 0.575, 0.01, 0.3]) cbar_temp = colorbar(img2, cax=cbaxes_temp) cbar_temp.ax.tick_params(labelsize=16) # Low-res salinity ax = fig.add_subplot(2, 2, 3) img3 = PatchCollection(patches_low, cmap='jet') img3.set_array(salt_low) img3.set_edgecolor('face') img3.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img3) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) title('Low-res salinity (psu)', fontsize=20) xlabel('Latitude', fontsize=16) ylabel('Depth (m)', fontsize=16) # High-res salinity ax = fig.add_subplot(2, 2, 4) img4 = PatchCollection(patches_high, cmap='jet') img4.set_array(salt_high) img4.set_edgecolor('face') img4.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img4) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) title('High-res salinity (psu)', fontsize=20) xlabel('Latitude', fontsize=16) # Add colorbar for salinity cbaxes_salt = fig.add_axes([0.92, 0.125, 0.01, 0.3]) cbar_salt = colorbar(img4, cax=cbaxes_salt) cbar_salt.ax.tick_params(labelsize=16) # Main title suptitle(shelf_names[index] + lon_string, fontsize=28) #fig.show() fig.savefig(fig_heads[index] + '_zonal_ts.png')
def mip_zonal_cavity_ts (roms_grid, roms_file, fesom_mesh_path_lr, fesom_file_lr, fesom_mesh_path_hr, fesom_file_hr): # Name of each ice shelf shelf_names = ['Larsen D Ice Shelf', 'Larsen C Ice Shelf', 'Wilkins & George VI & Stange Ice Shelves', 'Ronne-Filchner Ice Shelf', 'Abbot Ice Shelf', 'Pine Island Glacier Ice Shelf', 'Thwaites Ice Shelf', 'Dotson Ice Shelf', 'Getz Ice Shelf', 'Nickerson Ice Shelf', 'Sulzberger Ice Shelf', 'Mertz Ice Shelf', 'Totten & Moscow University Ice Shelves', 'Shackleton Ice Shelf', 'West Ice Shelf', 'Amery Ice Shelf', 'Prince Harald Ice Shelf', 'Baudouin & Borchgrevink Ice Shelves', 'Lazarev Ice Shelf', 'Nivl Ice Shelf', 'Fimbul & Jelbart & Ekstrom Ice Shelves', 'Brunt & Riiser-Larsen Ice Shelves', 'Ross Ice Shelf'] # Beginnings of filenames for figures fig_heads = ['larsen_d', 'larsen_c', 'wilkins_georgevi_stange', 'ronne_filchner', 'abbot', 'pig', 'thwaites', 'dotson', 'getz', 'nickerson', 'sulzberger', 'mertz', 'totten_moscowuni', 'shackleton', 'west', 'amery', 'prince_harald', 'baudouin_borchgrevink', 'lazarev', 'nivl', 'fimbul_jelbart_ekstrom', 'brunt_riiser_larsen', 'ross'] # Longitudes intersecting each ice shelf lon0 = [-60, -62, -68, -55, -93, -101, -106, -113, -120, -145, -150, 145, 116, 96, 85, 71, 36, 25, 15, 11, -1, -20, 180] # Latitude bounds for each ice shelf lat_min = [-73.1, -69.35, -73.1, -82.6, -73.28, -75.4, -75.5, -75, -74.9, -75.9, -77.8, -67.7, -67.17, -66.67, -67.25, -72, -69.7, -71, -70.4, -70.75, -71.83, -75.6, -84.6] lat_max = [-72, -66.13, -70, -75.5, -72.3, -74.4, -74.67, -74, -73.5, -75.3, -76.41, -67, -66.5, -64.83, -66.25, -68.5, -68.7, -69.9, -69.33, -69.83, -69.33, -72.9, -77] num_shelves = len(shelf_names) # ROMS grid parameters theta_s = 7.0 theta_b = 2.0 hc = 250 N = 31 print 'Setting up ROMS' # Start with grid id = Dataset(roms_grid, 'r') h = id.variables['h'][:,:] zice = id.variables['zice'][:,:] lon_2d = id.variables['lon_rho'][:,:] lat_2d = id.variables['lat_rho'][:,:] id.close() # Get a 3D array of z-coordinates; sc_r and Cs_r are unused in this script z_3d, sc_r, Cs_r = calc_z(h, zice, theta_s, theta_b, hc, N) # Read temperature and salinity id = Dataset(roms_file, 'r') roms_temp_3d = id.variables['temp'][0,:,:,:] roms_salt_3d = id.variables['salt'][0,:,:,:] id.close() print 'Setting up low-res FESOM' # Build the regular FESOM grid elm2D_lr = fesom_grid(fesom_mesh_path_lr) # Read temperature and salinity at every node id = Dataset(fesom_file_lr, 'r') fesom_temp_nodes_lr = id.variables['temp'][0,:] fesom_salt_nodes_lr = id.variables['salt'][0,:] id.close() print 'Setting up high-res FESOM' elm2D_hr = fesom_grid(fesom_mesh_path_hr) id = Dataset(fesom_file_hr, 'r') fesom_temp_nodes_hr = id.variables['temp'][0,:] fesom_salt_nodes_hr = id.variables['salt'][0,:] id.close() # Loop over ice shelves for index in range(num_shelves): print 'Processing ' + shelf_names[index] # Figure out what to write on the title about longitude if lon0[index] < 0: lon_string = ' ('+str(-lon0[index])+r'$^{\circ}$W)' else: lon_string = ' ('+str(lon0[index])+r'$^{\circ}$E)' # MetROMS # Make sure longitude is between 0 and 360 roms_lon0 = lon0[index] if roms_lon0 < 0: roms_lon0 += 360 # Interpolate to given longitude roms_temp, roms_z, roms_lat = interp_lon_roms(roms_temp_3d, z_3d, lat_2d, lon_2d, roms_lon0) roms_salt, roms_z, roms_lat = interp_lon_roms(roms_salt_3d, z_3d, lat_2d, lon_2d, roms_lon0) # Figure out deepest depth flag = (roms_lat >= lat_min[index])*(roms_lat <= lat_max[index]) depth_min_tmp = amin(roms_z[flag]) # Round down to nearest 50 metres depth_min = floor(depth_min_tmp/50)*50 # FESOM low-res # Build arrays of SideElements making up zonal slices selements_temp_lr = fesom_sidegrid(elm2D_lr, fesom_temp_nodes_lr, lon0[index], lat_max[index]) selements_salt_lr = fesom_sidegrid(elm2D_lr, fesom_salt_nodes_lr, lon0[index], lat_max[index]) # Build array of quadrilateral patches for the plots, and data values # corresponding to each SideElement patches_lr = [] fesom_temp_lr = [] for selm in selements_temp_lr: # Make patch coord = transpose(vstack((selm.y, selm.z))) patches_lr.append(Polygon(coord, True, linewidth=0.)) # Save data value fesom_temp_lr.append(selm.var) fesom_temp_lr = array(fesom_temp_lr) # Salinity has same patches but different values fesom_salt_lr = [] for selm in selements_salt_lr: fesom_salt_lr.append(selm.var) fesom_salt_lr = array(fesom_salt_lr) # FESOM high-res selements_temp_hr = fesom_sidegrid(elm2D_hr, fesom_temp_nodes_hr, lon0[index], lat_max[index]) selements_salt_hr = fesom_sidegrid(elm2D_hr, fesom_salt_nodes_hr, lon0[index], lat_max[index]) patches_hr = [] fesom_temp_hr = [] for selm in selements_temp_hr: coord = transpose(vstack((selm.y, selm.z))) patches_hr.append(Polygon(coord, True, linewidth=0.)) fesom_temp_hr.append(selm.var) fesom_temp_hr = array(fesom_temp_hr) fesom_salt_hr = [] for selm in selements_salt_hr: fesom_salt_hr.append(selm.var) fesom_salt_hr = array(fesom_salt_hr) # Find bounds on each variable temp_min = amin(array([amin(roms_temp[flag]), amin(fesom_temp_lr), amin(fesom_temp_hr)])) temp_max = amax(array([amax(roms_temp[flag]), amax(fesom_temp_lr), amax(fesom_temp_hr)])) salt_min = amin(array([amin(roms_salt[flag]), amin(fesom_salt_lr), amin(fesom_salt_hr)])) salt_max = amax(array([amax(roms_salt[flag]), amax(fesom_salt_lr), amax(fesom_salt_hr)])) # Plot fig = figure(figsize=(24,12)) # MetROMS temperature ax = fig.add_subplot(2, 3, 1) pcolor(roms_lat, roms_z, roms_temp, vmin=temp_min, vmax=temp_max, cmap='jet') title(r'MetROMS temperature ($^{\circ}$C)', fontsize=20) ylabel('Depth (m)', fontsize=16) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) # FESOM low-res temperature ax = fig.add_subplot(2, 3, 2) img = PatchCollection(patches_lr, cmap='jet') img.set_array(fesom_temp_lr) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) title(r'FESOM (low-res) temperature ($^{\circ}$C)', fontsize=20) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) # FESOM high-res temperature ax = fig.add_subplot(2, 3, 3) img = PatchCollection(patches_hr, cmap='jet') img.set_array(fesom_temp_hr) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) title(r'FESOM (high-res) temperature ($^{\circ}$C)', fontsize=20) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) # Add colorbar for temperature cbaxes = fig.add_axes([0.92, 0.575, 0.01, 0.3]) cbar = colorbar(img, cax=cbaxes) cbar.ax.tick_params(labelsize=16) # MetROMS salinity ax = fig.add_subplot(2, 3, 4) pcolor(roms_lat, roms_z, roms_salt, vmin=salt_min, vmax=salt_max, cmap='jet') title('MetROMS salinity (psu)', fontsize=20) xlabel('Latitude', fontsize=16) ylabel('Depth (m)', fontsize=16) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) # FESOM low-res salinity ax = fig.add_subplot(2, 3, 5) img = PatchCollection(patches_lr, cmap='jet') img.set_array(fesom_salt_lr) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) title(r'FESOM (low-res) salinity (psu)', fontsize=20) xlabel('Latitude', fontsize=16) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) # FESOM high-res salinity ax = fig.add_subplot(2, 3, 6) img = PatchCollection(patches_hr, cmap='jet') img.set_array(fesom_salt_hr) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) title(r'FESOM (high-res) salinity (psu)', fontsize=20) xlabel('Latitude', fontsize=16) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) # Add colorbar for salinity cbaxes = fig.add_axes([0.92, 0.125, 0.01, 0.3]) cbar = colorbar(img, cax=cbaxes) cbar.ax.tick_params(labelsize=16) # Main title suptitle(shelf_names[index] + lon_string, fontsize=28) #fig.show() fig.savefig(fig_heads[index] + '_zonal_ts.png')
def zonal_cavity_ts_rcp(mesh_path, spinup_path, rcp_path, fig_dir=''): file_name_beg = spinup_path + 'annual_avg.oce.mean.1996.2005.nc' file_name_end = rcp_path + 'annual_avg.oce.mean.2091.2100.nc' # Name of each ice shelf shelf_names = [ 'Larsen D Ice Shelf', 'Larsen C Ice Shelf', 'Wilkins & George VI & Stange Ice Shelves', 'Ronne-Filchner Ice Shelf', 'Abbot Ice Shelf', 'Pine Island Glacier Ice Shelf', 'Thwaites Ice Shelf', 'Dotson Ice Shelf', 'Getz Ice Shelf', 'Nickerson Ice Shelf', 'Sulzberger Ice Shelf', 'Mertz Ice Shelf', 'Totten & Moscow University Ice Shelves', 'Shackleton Ice Shelf', 'West Ice Shelf', 'Amery Ice Shelf', 'Prince Harald Ice Shelf', 'Baudouin & Borchgrevink Ice Shelves', 'Lazarev Ice Shelf', 'Nivl Ice Shelf', 'Fimbul & Jelbart & Ekstrom Ice Shelves', 'Brunt & Riiser-Larsen Ice Shelves', 'Ross Ice Shelf' ] # Beginnings of filenames for figures fig_heads = [ 'larsen_d', 'larsen_c', 'wilkins_georgevi_stange', 'ronne_filchner', 'abbot', 'pig', 'thwaites', 'dotson', 'getz', 'nickerson', 'sulzberger', 'mertz', 'totten_moscowuni', 'shackleton', 'west', 'amery', 'prince_harald', 'baudouin_borchgrevink', 'lazarev', 'nivl', 'fimbul_jelbart_ekstrom', 'brunt_riiser_larsen', 'ross' ] # Longitudes intersecting each ice shelf lon0 = [ -60, -62, -68, -55, -93, -101, -106, -113, -120, -145, -150, 145, 116, 96, 85, 71, 36, 25, 15, 11, -1, -20, 180 ] # Latitude bounds for each ice shelf lat_min = [ -73.1, -69.35, -73.1, -82.6, -73.28, -75.4, -75.5, -75, -74.9, -75.9, -77.8, -67.7, -67.17, -66.67, -67.25, -72, -69.7, -71, -70.4, -70.75, -71.83, -75.6, -84.6 ] lat_max = [ -72, -66.13, -70, -75.5, -72.3, -74.4, -74.67, -74, -73.5, -75.3, -76.41, -67, -66.5, -64.83, -66.25, -68.5, -68.7, -69.9, -69.33, -69.83, -69.33, -72.9, -77 ] num_shelves = len(shelf_names) print 'Building FESOM mesh' elm2D = fesom_grid(mesh_path) print 'Reading temperature and salinity data' id = Dataset(file_name_beg, 'r') temp_nodes_beg = id.variables['temp'][0, :] salt_nodes_beg = id.variables['salt'][0, :] id.close() id = Dataset(file_name_end, 'r') temp_nodes_end = id.variables['temp'][0, :] salt_nodes_end = id.variables['salt'][0, :] id.close() temp_nodes_diff = temp_nodes_end - temp_nodes_beg salt_nodes_diff = salt_nodes_end - salt_nodes_beg # Loop over ice shelves for index in range(num_shelves): print 'Processing ' + shelf_names[index] # Figure out what to write on the title about longitude if lon0[index] < 0: lon_string = ' (' + str(-lon0[index]) + r'$^{\circ}$W)' else: lon_string = ' (' + str(lon0[index]) + r'$^{\circ}$E)' # Build arrays of SideElements making up zonal slices selements_temp_beg = fesom_sidegrid(elm2D, temp_nodes_beg, lon0[index], lat_max[index]) selements_salt_beg = fesom_sidegrid(elm2D, salt_nodes_beg, lon0[index], lat_max[index]) selements_temp_end = fesom_sidegrid(elm2D, temp_nodes_end, lon0[index], lat_max[index]) selements_salt_end = fesom_sidegrid(elm2D, salt_nodes_end, lon0[index], lat_max[index]) selements_temp_diff = fesom_sidegrid(elm2D, temp_nodes_diff, lon0[index], lat_max[index]) selements_salt_diff = fesom_sidegrid(elm2D, salt_nodes_diff, lon0[index], lat_max[index]) # Build array of quadrilateral patches for the plots, and data values # corresponding to each SideElement patches = [] temp_beg = [] for selm in selements_temp_beg: # Make patch coord = transpose(vstack((selm.y, selm.z))) patches.append(Polygon(coord, True, linewidth=0.)) # Save data value temp_beg.append(selm.var) temp_beg = array(temp_beg) # Other variables have same patches but different values salt_beg = [] for selm in selements_salt_beg: salt_beg.append(selm.var) salt_beg = array(salt_beg) temp_end = [] for selm in selements_temp_end: temp_end.append(selm.var) temp_end = array(temp_end) salt_end = [] for selm in selements_salt_end: salt_end.append(selm.var) salt_end = array(salt_end) temp_diff = [] for selm in selements_temp_diff: temp_diff.append(selm.var) temp_diff = array(temp_diff) salt_diff = [] for selm in selements_salt_diff: salt_diff.append(selm.var) salt_diff = array(salt_diff) # Find bounds on each variable temp_min = min(amin(temp_beg), amin(temp_end)) temp_max = max(amax(temp_beg), amax(temp_end)) temp_max_diff = amax(abs(temp_diff)) salt_min = min(amin(salt_beg), amin(salt_end)) salt_max = max(amax(salt_beg), amax(salt_end)) salt_max_diff = amax(abs(salt_diff)) # Find deepest depth depth_min = 0 for selm in selements_temp_beg: depth_min = min(depth_min, amin(selm.z)) # Round down to nearest 50 metres depth_min = floor(depth_min / 50) * 50 # Plot fig = figure(figsize=(24, 12)) # Temperature (beginning) ax = fig.add_subplot(2, 3, 1) img = PatchCollection(patches, cmap='jet') img.set_array(temp_beg) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) title(r'Temperature ($^{\circ}$C), 1996-2005', fontsize=20) ylabel('Depth (m)', fontsize=16) # Add colorbar for absolute temperature cbaxes_temp = fig.add_axes([0.05, 0.575, 0.01, 0.3]) cbar_temp = colorbar(img, cax=cbaxes_temp) cbar_temp.ax.tick_params(labelsize=16) # Temperature (end) ax = fig.add_subplot(2, 3, 2) img = PatchCollection(patches, cmap='jet') img.set_array(temp_end) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) title(r'Temperature ($^{\circ}$C), 2091-2100', fontsize=20) ylabel('Depth (m)', fontsize=16) # Temperature (difference) ax = fig.add_subplot(2, 3, 3) img = PatchCollection(patches, cmap='RdBu_r') img.set_array(temp_diff) img.set_edgecolor('face') img.set_clim(vmin=-temp_max_diff, vmax=temp_max_diff) ax.add_collection(img) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) title(r'Temperature ($^{\circ}$C), change', fontsize=20) ylabel('Depth (m)', fontsize=16) # Add colorbar for temperature difference cbaxes_dtemp = fig.add_axes([0.92, 0.575, 0.01, 0.3]) cbar_dtemp = colorbar(img, cax=cbaxes_dtemp) cbar_dtemp.ax.tick_params(labelsize=16) # Salinity (beginning) ax = fig.add_subplot(2, 3, 4) img = PatchCollection(patches, cmap='jet') img.set_array(salt_beg) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) title('Salinity (psu), 1995-2005', fontsize=20) ylabel('Depth (m)', fontsize=16) # Add colorbar for absolute salinity cbaxes_salt = fig.add_axes([0.05, 0.125, 0.01, 0.3]) cbar_salt = colorbar(img, cax=cbaxes_salt) cbar_salt.ax.tick_params(labelsize=16) # Salinity (end) ax = fig.add_subplot(2, 3, 5) img = PatchCollection(patches, cmap='jet') img.set_array(salt_end) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) title('Salinity (psu), 2091-2100', fontsize=20) ylabel('Depth (m)', fontsize=16) # Salinity (difference) ax = fig.add_subplot(2, 3, 6) img = PatchCollection(patches, cmap='RdBu_r') img.set_array(salt_diff) img.set_edgecolor('face') img.set_clim(vmin=-salt_max_diff, vmax=salt_max_diff) ax.add_collection(img) xlim([lat_min[index], lat_max[index]]) ylim([depth_min, 0]) title('Salinity (psu), change', fontsize=20) ylabel('Depth (m)', fontsize=16) # Add colorbar for salinity difference cbaxes_dsalt = fig.add_axes([0.92, 0.125, 0.01, 0.3]) cbar_dsalt = colorbar(img, cax=cbaxes_dsalt) cbar_dsalt.ax.tick_params(labelsize=16) # Main title suptitle(shelf_names[index] + lon_string, fontsize=28) #fig.show() fig.savefig(fig_dir + fig_heads[index] + '_zonal_ts.png')
def timeseries_dpt (mesh_path, ocn_file, log_file): circumpolar = False # Don't transform x and y coordinates, we need them! cross_180 = False # Don't make second copies of elements that cross 180E days_per_output = 5 # Number of days for each output step # Longitude of Drake Passage zonal slice lon0 = -67 # Latitude bounds on Drake Passage zonal slice lat_min = -68 lat_max = -54.5 dpt = [] # Check if the log file exists if exists(log_file): print 'Reading previously calculated values' f = open(log_file, 'r') # Skip the first line (header) f.readline() for line in f: dpt.append(float(line)) f.close() print 'Building grid' # First get regular 2D elements elm2D = fesom_grid(mesh_path, circumpolar, cross_180) # Read longitude and latitude of each node in order (needed for rotation) fid = open(mesh_path + 'nod3d.out', 'r') fid.readline() lon = [] lat = [] for line in fid: tmp = line.split() lon_tmp = float(tmp[1]) lat_tmp = float(tmp[2]) if lon_tmp < -180: lon_tmp += 360 elif lon_tmp > 180: lon_tmp -= 360 lon.append(lon_tmp) lat.append(lat_tmp) fid.close() lon = array(lon) lat = array(lat) print 'Reading data' id = Dataset(ocn_file, 'r') num_time = id.variables['time'].shape[0] # Read both u and v so we can rotate to get the real u u_r = id.variables['u'][:,:] v_r = id.variables['v'][:,:] id.close() print 'Unrotating velocity vector' u = zeros(shape(u_r)) # Rotate one time index at a time for t in range(num_time): u_tmp, v_tmp = unrotate_vector(lon, lat, u_r[t,:], v_r[t,:]) u[t,:] = u_tmp print 'Extracting zonal slice through Drake Passage' # Get quadrilateral elements in the latitude vs depth slice selements = fesom_sidegrid(elm2D, u, lon0, lat_max, lat_min) print 'Setting up arrays' # Eastward velocity at each element u_selm = zeros([num_time, len(selements)]) # Area of each element area_selm = zeros(len(selements)) # Loop over elements to fill these in for i in range(len(selements)): selm = selements[i] u_selm[:,i] = selm.var area_selm[i] = selm.area() # Build timeseries for t in range(num_time): # Integrate u*area and convert to Sv dpt.append(sum(u_selm[t,:]*area_selm)*1e-6) # Calculate time values time = arange(len(dpt))*days_per_output/365. print 'Plotting' clf() plot(time, dpt) xlabel('Years') ylabel('Drake Passage Transport (Sv)') grid(True) savefig('drakepsgtrans.png') print 'Saving results to log file' f = open(log_file, 'w') f.write('Drake Passage Transport (Sv):\n') for elm in dpt: f.write(str(elm) + '\n') f.close()
def zonal_slice_plot (mesh_path, file_path, var_name, tstep, lon0, depth_min, save=False, fig_name=None, set_limits=False, limits=None): # Set northern boundary and upper (surface) boundary lat_max = -50 depth_max = 0 # Font sizes for figure font_sizes = [30, 24, 20] # Read variable name and units for title id = Dataset(file_path, 'r') varid = id.variables[var_name] name = varid.getncattr('description') units = varid.getncattr('units') if lon0 < 0: lon_string = 'at ' + str(-lon0) + 'W' else: lon_string = 'at ' + str(lon0) + 'E' # Read data data = id.variables[var_name][tstep-1,:] # Check for vector variables that need to be unrotated if var_name in ['u', 'v']: # Read the rotated lat and lon fid = open(mesh_path + 'nod3d.out', 'r') fid.readline() lon = [] lat = [] for line in fid: tmp = line.split() lon_tmp = float(tmp[1]) lat_tmp = float(tmp[2]) if lon_tmp < -180: lon_tmp += 360 elif lon_tmp > 180: lon_tmp -= 360 lon.append(lon_tmp) lat.append(lat_tmp) fid.close() lon = array(lon) lat = array(lat) if var_name == 'u': u_data = data[:] v_data = id.variables['v'][tstep-1,:] u_data_lonlat, v_data_lonlat = unrotate_vector(lon, lat, u_data, v_data) data = u_data_lonlat[:] elif var_name == 'v': v_data = data[:] u_data = id.variables['u'][tstep-1,:] u_data_lonlat, v_data_lonlat = unrotate_vector(lon, lat, u_data, v_data) data = v_data_lonlat[:] id.close() # Build the regular FESOM grid elm2D = fesom_grid(mesh_path) # Build the array of SideElements making up the zonal slice selements = fesom_sidegrid(elm2D, data, lon0, lat_max) # Build an array of quadrilateral patches for the plot, and of data values # corresponding to each SideElement # Also find the minimum latitude of any SideElement patches = [] values = [] lat_min = lat_max for selm in selements: # Make patch coord = transpose(vstack((selm.y,selm.z))) patches.append(Polygon(coord, True, linewidth=0.)) # Save data value values.append(selm.var) # Update minimum latitude if needed lat_min = min(lat_min, amin(selm.y)) # Set southern boundary to be just south of the minimum latitude lat_min = lat_min-1 # Choose colour bounds if set_limits: # User-specified bounds var_min = limits[0] var_max = limits[1] if var_min == -var_max: # Bounds are centered on zero, so choose a blue-to-red colourmap # centered on yellow colour_map = 'RdYlBu_r' else: colour_map = 'jet' else: # Determine bounds automatically if var_name in ['u', 'v', 'w']: # Center levels on 0 for certain variables, with a blue-to-red # colourmap max_val = amax(abs(array(values))) var_min = -max_val var_max = max_val colour_map = 'RdYlBu_r' else: var_min = amin(array(values)) var_max = amax(array(values)) colour_map = 'jet' # Set up plot fig = figure(figsize=(16,8)) ax = fig.add_subplot(1,1,1) # Set colourmap for patches, and refer it to the values array img = PatchCollection(patches, cmap=colour_map) img.set_array(array(values)) img.set_edgecolor('face') # Add patches to plot ax.add_collection(img) # Configure plot xlim(lat_min, lat_max) ylim(depth_min, depth_max) title(name + ' (' + units + ') ' + lon_string, fontsize=font_sizes[0]) xlabel('Latitude', fontsize=font_sizes[1]) ylabel('Depth (m)', fontsize=font_sizes[1]) setp(ax.get_xticklabels(), fontsize=font_sizes[2]) setp(ax.get_yticklabels(), fontsize=font_sizes[2]) cbar = colorbar(img) cbar.ax.tick_params(labelsize=font_sizes[2]) img.set_clim(vmin=var_min, vmax=var_max) if save: fig.savefig(fig_name) else: fig.show()
def timeseries_dpt (mesh_path, ocn_file, log_file, fig_dir=''): circumpolar = False # Needs to be global for SideElements cross_180 = False # Don't make second copies of elements that cross 180E days_per_output = 5 # Number of days for each output step # Longitude of Drake Passage zonal slice lon0 = -67 # Latitude bounds on Drake Passage zonal slice lat_min = -68 lat_max = -54.5 dpt = [] # Check if the log file exists if exists(log_file): print 'Reading previously calculated values' f = open(log_file, 'r') # Skip the first line (header) f.readline() for line in f: dpt.append(float(line)) f.close() print 'Building grid' # First get regular 2D elements elm2D = fesom_grid(mesh_path, circumpolar, cross_180) # Read longitude and latitude of each node in order (needed for rotation) fid = open(mesh_path + 'nod3d.out', 'r') fid.readline() lon = [] lat = [] for line in fid: tmp = line.split() lon_tmp = float(tmp[1]) lat_tmp = float(tmp[2]) if lon_tmp < -180: lon_tmp += 360 elif lon_tmp > 180: lon_tmp -= 360 lon.append(lon_tmp) lat.append(lat_tmp) fid.close() lon = array(lon) lat = array(lat) print 'Reading data' id = Dataset(ocn_file, 'r') num_time = id.variables['time'].shape[0] # Read both u and v so we can rotate to get the real u u_r = id.variables['u'][:,:] v_r = id.variables['v'][:,:] id.close() print 'Unrotating velocity vector' u = zeros(shape(u_r)) # Rotate one time index at a time for t in range(num_time): u_tmp, v_tmp = unrotate_vector(lon, lat, u_r[t,:], v_r[t,:]) u[t,:] = u_tmp print 'Extracting zonal slice through Drake Passage' # Get quadrilateral elements in the latitude vs depth slice selements = fesom_sidegrid(elm2D, u, lon0, lat_max, lat_min) print 'Setting up arrays' # Eastward velocity at each element u_selm = zeros([num_time, len(selements)]) # Area of each element area_selm = zeros(len(selements)) # Loop over elements to fill these in for i in range(len(selements)): selm = selements[i] u_selm[:,i] = selm.var area_selm[i] = selm.area() # Build timeseries for t in range(num_time): # Integrate u*area and convert to Sv dpt.append(sum(u_selm[t,:]*area_selm)*1e-6) # Calculate time values time = arange(len(dpt))*days_per_output/365. print 'Plotting' clf() plot(time, dpt) xlabel('Years') ylabel('Drake Passage Transport (Sv)') grid(True) savefig(fig_dir + 'drakepsgtrans.png') print 'Saving results to log file' f = open(log_file, 'w') f.write('Drake Passage Transport (Sv):\n') for elm in dpt: f.write(str(elm) + '\n') f.close()
def zonal_ts_rcp_lon(lon0, lat_min, lat_max, save=False, fig_name=None): # File paths mesh_path = '/short/y99/kaa561/FESOM/mesh/meshB/' directory_beg = '/short/y99/kaa561/FESOM/highres_spinup/' directories = [ '/short/y99/kaa561/FESOM/rcp45_M/', '/short/y99/kaa561/FESOM/rcp45_A/', '/short/y99/kaa561/FESOM/rcp85_M/', '/short/y99/kaa561/FESOM/rcp85_A/', '/short/y99/kaa561/FESOM/highres_spinup/' ] file_beg = 'annual_avg.oce.mean.1996.2005.nc' file_end = 'annual_avg.oce.mean.2091.2100.nc' # Titles for plotting expt_names = [ 'RCP 4.5 M', 'RCP 4.5 A', 'RCP 8.5 M', 'RCP 8.5 A', 'CONTROL' ] num_expts = len(directories) # Start and end years for each period beg_years = [1996, 2005] end_years = [2091, 2100] # Figure out what to write on the title about longitude if lon0 < 0: lon_string = str(-lon0) + r'$^{\circ}$W' else: lon_string = str(lon0) + r'$^{\circ}$E' print 'Building FESOM mesh' elm2D = fesom_grid(mesh_path) print 'Reading temperature and salinity data' id = Dataset(directory_beg + file_beg, 'r') temp_nodes_beg = id.variables['temp'][0, :] salt_nodes_beg = id.variables['salt'][0, :] id.close() n3d = size(temp_nodes_beg) # Get anomalies for each experiment temp_nodes_diff = zeros([num_expts, n3d]) salt_nodes_diff = zeros([num_expts, n3d]) for expt in range(num_expts): id = Dataset(directories[expt] + file_end, 'r') temp_nodes_diff[expt, :] = id.variables['temp'][0, :] - temp_nodes_beg salt_nodes_diff[expt, :] = id.variables['salt'][0, :] - salt_nodes_beg print 'Interpolating to ' + lon_string # Build arrays of SideElements making up zonal slices # Start with beginning print '...' + str(beg_years[0]) + '-' + str(beg_years[1]) selements_temp_beg = fesom_sidegrid(elm2D, temp_nodes_beg, lon0, lat_max) selements_salt_beg = fesom_sidegrid(elm2D, salt_nodes_beg, lon0, lat_max) # Build array of quadrilateral patches for the plots, and data values # corresponding to each SideElement patches = [] temp_beg = [] for selm in selements_temp_beg: # Make patch coord = transpose(vstack((selm.y, selm.z))) patches.append(Polygon(coord, True, linewidth=0.)) # Save data value temp_beg.append(selm.var) temp_beg = array(temp_beg) # Salinity has same patches but different values salt_beg = [] for selm in selements_salt_beg: salt_beg.append(selm.var) salt_beg = array(salt_beg) # Repeat for anomalies for each experiment temp_diff = zeros([num_expts, len(patches)]) salt_diff = zeros([num_expts, len(patches)]) for expt in range(num_expts): print '...' + expt_names[expt] selements_temp_diff = fesom_sidegrid(elm2D, temp_nodes_diff[expt, :], lon0, lat_max) selements_salt_diff = fesom_sidegrid(elm2D, salt_nodes_diff[expt, :], lon0, lat_max) i = 0 for selm in selements_temp_diff: temp_diff[expt, i] = selm.var i += 1 i = 0 for selm in selements_salt_diff: salt_diff[expt, i] = selm.var i += 1 # Find bounds on each variable temp_min = amin(temp_beg) temp_max = amax(temp_beg) salt_min = amin(salt_beg) salt_max = amax(salt_beg) temp_max_diff = 2.0 salt_max_diff = 0.5 # Find deepest depth # Start with 0 depth_min = 0 # Modify with patches for selm in selements_temp_beg: depth_min = min(depth_min, amin(selm.z)) # Round down to nearest 50 metres depth_min = floor(depth_min / 50) * 50 print 'Plotting' fig = figure(figsize=(20, 16)) # Temperature gs_temp = GridSpec(2, 3) gs_temp.update(left=0.11, right=0.9, bottom=0.51, top=0.9, wspace=0.05, hspace=0.5) # Beginning ax = subplot(gs_temp[0, 0]) img = PatchCollection(patches, cmap='jet') img.set_array(temp_beg) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title(str(beg_years[0]) + '-' + str(beg_years[1]), fontsize=20) xlabel('Latitude', fontsize=16) ylabel('Depth (m)', fontsize=16) # Add a colorbar on the left cbaxes = fig.add_axes([0.02, 0.75, 0.015, 0.15]) cbar = colorbar(img, cax=cbaxes, extend='both') # Anomalies for each experiment for expt in range(num_expts): if expt < 2: ax = subplot(gs_temp[0, expt + 1]) else: ax = subplot(gs_temp[1, expt - 2]) img = PatchCollection(patches, cmap='RdBu_r') img.set_array(temp_diff[expt, :]) img.set_edgecolor('face') img.set_clim(vmin=-temp_max_diff, vmax=temp_max_diff) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title(expt_names[expt], fontsize=20) ax.set_xticklabels([]) ax.set_yticklabels([]) if expt == 0: xlabel(str(end_years[0]) + '-' + str(end_years[1]) + ' anomalies', fontsize=20) text(-69.5, 1200, r'Temperature ($^{\circ}$C) at ' + lon_string, fontsize=28) if expt == num_expts - 1: # Add a colorbar on the right cbaxes = fig.add_axes([0.92, 0.75, 0.015, 0.15]) cbar = colorbar(img, cax=cbaxes, extend='both') # Salinity gs_salt = GridSpec(2, 3) gs_salt.update(left=0.11, right=0.9, bottom=0.02, top=0.41, wspace=0.05, hspace=0.5) # Beginning ax = subplot(gs_salt[0, 0]) img = PatchCollection(patches, cmap='jet') img.set_array(salt_beg) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title(str(beg_years[0]) + '-' + str(beg_years[1]), fontsize=20) xlabel('Latitude', fontsize=16) ylabel('Depth (m)', fontsize=16) # Add a colorbar on the left cbaxes = fig.add_axes([0.02, 0.26, 0.015, 0.15]) cbar = colorbar(img, cax=cbaxes, extend='both') # Anomalies for each experiment for expt in range(num_expts): if expt < 2: ax = subplot(gs_salt[0, expt + 1]) else: ax = subplot(gs_salt[1, expt - 2]) img = PatchCollection(patches, cmap='RdBu_r') img.set_array(salt_diff[expt, :]) img.set_edgecolor('face') img.set_clim(vmin=-salt_max_diff, vmax=salt_max_diff) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title(expt_names[expt], fontsize=20) ax.set_xticklabels([]) ax.set_yticklabels([]) if expt == 0: xlabel(str(end_years[0]) + '-' + str(end_years[1]) + ' anomalies', fontsize=20) text(-68, 1200, 'Salinity (psu) at ' + lon_string, fontsize=28) if expt == num_expts - 1: # Add a colorbar on the right cbaxes = fig.add_axes([0.92, 0.26, 0.015, 0.15]) cbar = colorbar(img, cax=cbaxes, extend='both') if save: fig.savefig(fig_name) else: fig.show()
def amundsen_slices_before_after(rcp, model, save=False, fig_name=None): # File paths mesh_path = '/short/y99/kaa561/FESOM/mesh/meshB/' file_beg = '/short/y99/kaa561/FESOM/highres_spinup/sept.oce.1996.2005.nc' file_end = '/short/y99/kaa561/FESOM/rcp' + rcp + '_' + model + '/sept.oce.2091.2100.nc' # Spatial bounds and labels lon0 = -104 lon_string = str(int(round(-lon0))) + r'$^{\circ}$W' lat_min = -75.1 lat_max = -70.8 lat_ticks = arange(-75, -71 + 1, 1) lat_labels = [] for lat in lat_ticks: lat_labels.append(str(int(round(-lat))) + r'$^{\circ}$S') depth_min = -1200 depth_max = 0 depth_ticks = arange(-1000, 0 + 250, 250) depth_labels = [] for depth in depth_ticks: depth_labels.append(str(int(round(-depth)))) if model == 'M': model_title = 'MMM' elif model == 'A': model_title = 'ACCESS' # Bounds on colourbars temp_min = -1.8 temp_max = 1.1 temp_ticks = arange(-1.5, 1 + 0.5, 0.5) salt_min = 33.6 salt_max = 34.6 salt_ticks = arange(33.6, 34.6 + 0.2, 0.2) # Density contours to plot density_contours = [27.45, 27.55] # Parameters for regular grid interpolation (needed for density contours) num_lat = 500 num_depth = 250 print 'Building FESOM mesh' elm2D = fesom_grid(mesh_path) print 'Reading temperature and salinity data' id = Dataset(file_beg, 'r') temp_nodes_beg = id.variables['temp'][0, :] salt_nodes_beg = id.variables['salt'][0, :] id.close() id = Dataset(file_end, 'r') temp_nodes_end = id.variables['temp'][0, :] salt_nodes_end = id.variables['salt'][0, :] print 'Calculating density' density_nodes_beg = unesco(temp_nodes_beg, salt_nodes_beg, zeros(shape(temp_nodes_beg))) - 1000 density_nodes_end = unesco(temp_nodes_end, salt_nodes_end, zeros(shape(temp_nodes_end))) - 1000 print 'Interpolating to ' + str(lon0) # Build arrays of SideElements making up zonal slices # Start with beginning selements_temp_beg = fesom_sidegrid(elm2D, temp_nodes_beg, lon0, lat_max) selements_salt_beg = fesom_sidegrid(elm2D, salt_nodes_beg, lon0, lat_max) # Build array of quadrilateral patches for the plots, and data values # corresponding to each SideElement patches = [] temp_beg = [] for selm in selements_temp_beg: # Make patch coord = transpose(vstack((selm.y, selm.z))) patches.append(Polygon(coord, True, linewidth=0.)) # Save data value temp_beg.append(selm.var) temp_beg = array(temp_beg) print 'Temp bounds, beginning: ' + str(amin(temp_beg)) + ' ' + str( amax(temp_beg)) # Salinity has same patches but different values salt_beg = [] for selm in selements_salt_beg: salt_beg.append(selm.var) salt_beg = array(salt_beg) print 'Salt bounds, beginning: ' + str(amin(salt_beg)) + ' ' + str( amax(salt_beg)) # Repeat for end selements_temp_end = fesom_sidegrid(elm2D, temp_nodes_end, lon0, lat_max) selements_salt_end = fesom_sidegrid(elm2D, salt_nodes_end, lon0, lat_max) temp_end = [] for selm in selements_temp_end: temp_end.append(selm.var) temp_end = array(temp_end) print 'Temp bounds, end: ' + str(amin(temp_end)) + ' ' + str( amax(temp_end)) salt_end = [] for selm in selements_salt_end: salt_end.append(selm.var) salt_end = array(salt_end) print 'Salt bounds, end: ' + str(amin(salt_end)) + ' ' + str( amax(salt_end)) print 'Interpolating density to regular grid' lat_reg = linspace(lat_min, lat_max, num_lat) depth_reg = linspace(-depth_max, -depth_min, num_depth) density_reg_beg = zeros([num_depth, num_lat]) density_reg_end = zeros([num_depth, num_lat]) density_reg_beg[:, :] = NaN density_reg_end[:, :] = NaN # For each element, check if a point on the regular grid lies # within. If so, do barycentric interpolation to that point, at each # depth on the regular grid. for elm in elm2D: # Check if this element crosses lon0 if amin(elm.lon) < lon0 and amax(elm.lon) > lon0: # Check if we are within the latitude bounds if amax(elm.lat) > lat_min and amin(elm.lat) < lat_max: # Find largest regular latitude value south of Element tmp = nonzero(lat_reg > amin(elm.lat))[0] if len(tmp) == 0: # Element crosses the southern boundary jS = 0 else: jS = tmp[0] - 1 # Find smallest regular latitude north of Element tmp = nonzero(lat_reg > amax(elm.lat))[0] if len(tmp) == 0: # Element crosses the northern boundary jN = num_lat else: jN = tmp[0] for j in range(jS + 1, jN): # There is a chance that the regular gridpoint at j # lies within this element lat0 = lat_reg[j] if in_triangle(elm, lon0, lat0): # Yes it does # Get area of entire triangle area = triangle_area(elm.lon, elm.lat) # Get area of each sub-triangle formed by (lon0, lat0) area0 = triangle_area([lon0, elm.lon[1], elm.lon[2]], [lat0, elm.lat[1], elm.lat[2]]) area1 = triangle_area([lon0, elm.lon[0], elm.lon[2]], [lat0, elm.lat[0], elm.lat[2]]) area2 = triangle_area([lon0, elm.lon[0], elm.lon[1]], [lat0, elm.lat[0], elm.lat[1]]) # Find fractional area of each cff = [area0 / area, area1 / area, area2 / area] # Interpolate each depth value for k in range(num_depth): # Linear interpolation in the vertical for the # value at each corner of the triangle node_vals_beg = [] node_vals_end = [] for n in range(3): id1, id2, coeff1, coeff2 = elm.nodes[ n].find_depth(depth_reg[k]) if any(isnan(array([id1, id2, coeff1, coeff2]))): # No ocean data here (seafloor or ice shelf) node_vals_beg.append(NaN) node_vals_end.append(NaN) else: node_vals_beg.append( coeff1 * density_nodes_beg[id1] + coeff2 * density_nodes_beg[id2]) node_vals_end.append( coeff1 * density_nodes_end[id1] + coeff2 * density_nodes_end[id2]) if any(isnan(node_vals_beg)): pass else: # Barycentric interpolation for the value at # lon0, lat0 density_reg_beg[k, j] = sum( array(cff) * array(node_vals_beg)) density_reg_end[k, j] = sum( array(cff) * array(node_vals_end)) density_reg_beg = ma.masked_where(isnan(density_reg_beg), density_reg_beg) density_reg_end = ma.masked_where(isnan(density_reg_end), density_reg_end) depth_reg = -1 * depth_reg print 'Plotting' fig = figure(figsize=(16, 10)) # Temperature gs_temp = GridSpec(1, 2) gs_temp.update(left=0.08, right=0.9, bottom=0.5, top=0.88, wspace=0.05, hspace=0.5) # Beginning ax = subplot(gs_temp[0, 0]) img = PatchCollection(patches, cmap='jet') img.set_array(temp_beg) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) # Overlay density contours on regular grid contour(lat_reg, depth_reg, density_reg_beg, levels=density_contours, colors='black') xlim([lat_min, lat_max]) ylim([depth_min, depth_max]) title(r'Temperature ($^{\circ}$C), 1996-2005', fontsize=24) ax.set_xticks(lat_ticks) ax.set_xticklabels([]) ax.set_yticks(depth_ticks) ax.set_yticklabels(depth_labels, fontsize=16) ylabel('Depth (m)', fontsize=18) # End ax = subplot(gs_temp[0, 1]) img = PatchCollection(patches, cmap='jet') img.set_array(temp_end) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) contour(lat_reg, depth_reg, density_reg_end, levels=density_contours, colors='black') xlim([lat_min, lat_max]) ylim([depth_min, depth_max]) title(r'Temperature ($^{\circ}$C), 2091-2100', fontsize=24) ax.set_xticks(lat_ticks) ax.set_xticklabels([]) ax.set_yticks(depth_ticks) ax.set_yticklabels([]) # Add a colorbar on the right cbaxes = fig.add_axes([0.92, 0.55, 0.02, 0.28]) cbar = colorbar(img, cax=cbaxes, extend='both', ticks=temp_ticks) cbar.ax.tick_params(labelsize=16) # Salinity gs_salt = GridSpec(1, 2) gs_salt.update(left=0.08, right=0.9, bottom=0.07, top=0.45, wspace=0.05, hspace=0.5) # Beginning ax = subplot(gs_salt[0, 0]) img = PatchCollection(patches, cmap='jet') img.set_array(salt_beg) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) contour(lat_reg, depth_reg, density_reg_beg, levels=density_contours, colors='black') xlim([lat_min, lat_max]) ylim([depth_min, depth_max]) title('Salinity (psu), 1996-2005', fontsize=24) ax.set_xticks(lat_ticks) ax.set_xticklabels(lat_labels, fontsize=16) xlabel('Latitude', fontsize=18) ax.set_yticks(depth_ticks) ax.set_yticklabels(depth_labels, fontsize=16) ylabel('Depth (m)', fontsize=18) # End ax = subplot(gs_salt[0, 1]) img = PatchCollection(patches, cmap='jet') img.set_array(salt_end) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) contour(lat_reg, depth_reg, density_reg_end, levels=density_contours, colors='black') xlim([lat_min, lat_max]) ylim([depth_min, depth_max]) title('Salinity (psu), 2091-2100', fontsize=24) ax.set_xticks(lat_ticks) ax.set_xticklabels(lat_labels, fontsize=16) xlabel('Latitude', fontsize=18) ax.set_yticks(lat_ticks) ax.set_yticklabels([]) # Add a colorbar on the right cbaxes = fig.add_axes([0.92, 0.12, 0.02, 0.28]) cbar = colorbar(img, cax=cbaxes, extend='both', ticks=salt_ticks) cbar.ax.tick_params(labelsize=16) # Main title suptitle('RCP ' + rcp[0] + '.' + rcp[1] + ' ' + model_title + ', ' + lon_string + ' (Amundsen Sea), September', fontsize=28) if save: fig.savefig(fig_name) else: fig.show()
def mip_drift_slices(roms_grid, roms_file, fesom_mesh_path_lr, fesom_file_lr, fesom_mesh_path_hr, fesom_file_hr): # Paths to ECCO2 files with initial conditions for temp and salt ecco_temp_file = '/short/m68/kaa561/metroms_iceshelf/data/originals/ECCO2/THETA.1440x720x50.199201.nc' ecco_salt_file = '/short/m68/kaa561/metroms_iceshelf/data/originals/ECCO2/SALT.1440x720x50.199201.nc' # Longitude to interpolate to (OE) lon0 = 0 # Bounds on plot lat_min = -73 lat_max = -30 depth_min = -6000 depth_max = 0 # ROMS grid parameters theta_s = 7.0 theta_b = 2.0 hc = 250 N = 31 # Bounds on colour scales for temperature and salinity temp_min = -2 temp_max = 6 salt_min = 33.9 salt_max = 34.9 # Contours to overlay temp_contour = 0.75 salt_contour = 34.5 # Parameters for FESOM regular grid interpolation (needed for contours) num_lat = 500 num_depth = 250 # Get longitude for the title if lon0 < 0: lon_string = str(int(round(-lon0))) + r'$^{\circ}$W' else: lon_string = str(int(round(lon0))) + r'$^{\circ}$E' print 'Processing ECCO2' id = Dataset(ecco_temp_file, 'r') # Read grid variables ecco_lat = id.variables['LATITUDE_T'][:] ecco_depth = -1 * id.variables['DEPTH_T'][:] if lon0 == 0: # Hard-coded lon0 = 0E: average between the first (0.125 E) and last # (359.875 E = -0.125 W) indices in the regular ECCO2 grid ecco_temp = 0.5 * (id.variables['THETA'][0, :, :, 0] + id.variables['THETA'][0, :, :, -1]) id.close() id = Dataset(ecco_salt_file, 'r') ecco_salt = 0.5 * (id.variables['SALT'][0, :, :, 0] + id.variables['SALT'][0, :, :, -1]) id.close() else: print 'lon0 is only coded for 0E at this time' #return print 'Processing ROMS' # Read grid variables we need id = Dataset(roms_grid, 'r') roms_lon_2d = id.variables['lon_rho'][:, :] roms_lat_2d = id.variables['lat_rho'][:, :] roms_h = id.variables['h'][:, :] roms_zice = id.variables['zice'][:, :] id.close() # Read temperature and salinity id = Dataset(roms_file, 'r') roms_temp_3d = id.variables['temp'][0, :, :, :] roms_salt_3d = id.variables['salt'][0, :, :, :] id.close() # Get a 3D array of z-coordinates; sc_r and Cs_r are unused in this script roms_z_3d, sc_r, Cs_r = calc_z(roms_h, roms_zice, theta_s, theta_b, hc, N) # Make sure we are in the range 0-360 if lon0 < 0: lon0 += 360 # Interpolate to lon0 roms_temp, roms_z, roms_lat = interp_lon_roms(roms_temp_3d, roms_z_3d, roms_lat_2d, roms_lon_2d, lon0) roms_salt, roms_z, roms_lat = interp_lon_roms(roms_salt_3d, roms_z_3d, roms_lat_2d, roms_lon_2d, lon0) # Switch back to range -180-180 if lon0 > 180: lon0 -= 360 print 'Processing low-res FESOM' # Build regular elements elements_lr = fesom_grid(fesom_mesh_path_lr) # Read temperature and salinity id = Dataset(fesom_file_lr, 'r') fesom_temp_nodes_lr = id.variables['temp'][0, :] fesom_salt_nodes_lr = id.variables['salt'][0, :] id.close() # Make SideElements selements_temp_lr = fesom_sidegrid(elements_lr, fesom_temp_nodes_lr, lon0, lat_max) selements_salt_lr = fesom_sidegrid(elements_lr, fesom_salt_nodes_lr, lon0, lat_max) # Build an array of quadrilateral patches for the plot, and of data values # corresponding to each SideElement patches_lr = [] fesom_temp_lr = [] for selm in selements_temp_lr: # Make patch coord = transpose(vstack((selm.y, selm.z))) patches_lr.append(Polygon(coord, True, linewidth=0.)) # Save data value fesom_temp_lr.append(selm.var) # Repeat for salinity fesom_salt_lr = [] for selm in selements_salt_lr: fesom_salt_lr.append(selm.var) # Interpolate to regular grid so we can overlay contours lat_reg = linspace(lat_min, lat_max, num_lat) depth_reg = linspace(-depth_max, -depth_min, num_depth) temp_reg_lr = zeros([num_depth, num_lat]) salt_reg_lr = zeros([num_depth, num_lat]) temp_reg_lr[:, :] = NaN salt_reg_lr[:, :] = NaN # For each element, check if a point on the regular grid lies # within. If so, do barycentric interpolation to that point, at each # depth on the regular grid. for elm in elements_lr: # Check if this element crosses lon0 if amin(elm.lon) < lon0 and amax(elm.lon) > lon0: # Check if we are within the latitude bounds if amax(elm.lat) > lat_min and amin(elm.lat) < lat_max: # Find largest regular latitude value south of Element tmp = nonzero(lat_reg > amin(elm.lat))[0] if len(tmp) == 0: # Element crosses the southern boundary jS = 0 else: jS = tmp[0] - 1 # Find smallest regular latitude north of Element tmp = nonzero(lat_reg > amax(elm.lat))[0] if len(tmp) == 0: # Element crosses the northern boundary jN = num_lat else: jN = tmp[0] for j in range(jS + 1, jN): # There is a chance that the regular gridpoint at j # lies within this element lat0 = lat_reg[j] if in_triangle(elm, lon0, lat0): # Yes it does # Get area of entire triangle area = triangle_area(elm.lon, elm.lat) # Get area of each sub-triangle formed by (lon0, lat0) area0 = triangle_area([lon0, elm.lon[1], elm.lon[2]], [lat0, elm.lat[1], elm.lat[2]]) area1 = triangle_area([lon0, elm.lon[0], elm.lon[2]], [lat0, elm.lat[0], elm.lat[2]]) area2 = triangle_area([lon0, elm.lon[0], elm.lon[1]], [lat0, elm.lat[0], elm.lat[1]]) # Find fractional area of each cff = [area0 / area, area1 / area, area2 / area] # Interpolate each depth value for k in range(num_depth): # Linear interpolation in the vertical for the # value at each corner of the triangle node_vals_temp = [] node_vals_salt = [] for n in range(3): id1, id2, coeff1, coeff2 = elm.nodes[ n].find_depth(depth_reg[k]) if any(isnan(array([id1, id2, coeff1, coeff2]))): # No ocean data here (seafloor or ice shelf) node_vals_temp.append(NaN) node_vals_salt.append(NaN) else: node_vals_temp.append( coeff1 * fesom_temp_nodes_lr[id1] + coeff2 * fesom_temp_nodes_lr[id2]) node_vals_salt.append( coeff1 * fesom_salt_nodes_lr[id1] + coeff2 * fesom_salt_nodes_lr[id2]) if any(isnan(node_vals_temp)): pass else: # Barycentric interpolation for the value at # lon0, lat0 temp_reg_lr[k, j] = sum( array(cff) * array(node_vals_temp)) salt_reg_lr[k, j] = sum( array(cff) * array(node_vals_salt)) temp_reg_lr = ma.masked_where(isnan(temp_reg_lr), temp_reg_lr) salt_reg_lr = ma.masked_where(isnan(salt_reg_lr), salt_reg_lr) print 'Processing high-res FESOM' elements_hr = fesom_grid(fesom_mesh_path_hr) id = Dataset(fesom_file_hr, 'r') fesom_temp_nodes_hr = id.variables['temp'][0, :] fesom_salt_nodes_hr = id.variables['salt'][0, :] id.close() selements_temp_hr = fesom_sidegrid(elements_hr, fesom_temp_nodes_hr, lon0, lat_max) selements_salt_hr = fesom_sidegrid(elements_hr, fesom_salt_nodes_hr, lon0, lat_max) patches_hr = [] fesom_temp_hr = [] for selm in selements_temp_hr: coord = transpose(vstack((selm.y, selm.z))) patches_hr.append(Polygon(coord, True, linewidth=0.)) fesom_temp_hr.append(selm.var) fesom_salt_hr = [] for selm in selements_salt_hr: fesom_salt_hr.append(selm.var) lat_reg = linspace(lat_min, lat_max, num_lat) temp_reg_hr = zeros([num_depth, num_lat]) salt_reg_hr = zeros([num_depth, num_lat]) temp_reg_hr[:, :] = NaN salt_reg_hr[:, :] = NaN for elm in elements_hr: if amin(elm.lon) < lon0 and amax(elm.lon) > lon0: if amax(elm.lat) > lat_min and amin(elm.lat) < lat_max: tmp = nonzero(lat_reg > amin(elm.lat))[0] if len(tmp) == 0: jS = 0 else: jS = tmp[0] - 1 tmp = nonzero(lat_reg > amax(elm.lat))[0] if len(tmp) == 0: jN = num_lat else: jN = tmp[0] for j in range(jS + 1, jN): lat0 = lat_reg[j] if in_triangle(elm, lon0, lat0): area = triangle_area(elm.lon, elm.lat) area0 = triangle_area([lon0, elm.lon[1], elm.lon[2]], [lat0, elm.lat[1], elm.lat[2]]) area1 = triangle_area([lon0, elm.lon[0], elm.lon[2]], [lat0, elm.lat[0], elm.lat[2]]) area2 = triangle_area([lon0, elm.lon[0], elm.lon[1]], [lat0, elm.lat[0], elm.lat[1]]) cff = [area0 / area, area1 / area, area2 / area] for k in range(num_depth): node_vals_temp = [] node_vals_salt = [] for n in range(3): id1, id2, coeff1, coeff2 = elm.nodes[ n].find_depth(depth_reg[k]) if any(isnan(array([id1, id2, coeff1, coeff2]))): node_vals_temp.append(NaN) node_vals_salt.append(NaN) else: node_vals_temp.append( coeff1 * fesom_temp_nodes_hr[id1] + coeff2 * fesom_temp_nodes_hr[id2]) node_vals_salt.append( coeff1 * fesom_salt_nodes_hr[id1] + coeff2 * fesom_salt_nodes_hr[id2]) if any(isnan(node_vals_temp)): pass else: temp_reg_hr[k, j] = sum( array(cff) * array(node_vals_temp)) salt_reg_hr[k, j] = sum( array(cff) * array(node_vals_salt)) temp_reg_hr = ma.masked_where(isnan(temp_reg_hr), temp_reg_hr) salt_reg_hr = ma.masked_where(isnan(salt_reg_hr), salt_reg_hr) depth_reg = -1 * depth_reg # Set up axis labels the way we want them lat_ticks = arange(lat_min + 3, lat_max + 10, 10) lat_labels = [] for val in lat_ticks: lat_labels.append(str(int(round(-val))) + r'$^{\circ}$S') depth_ticks = range(depth_min + 1000, 0 + 1000, 1000) depth_labels = [] for val in depth_ticks: depth_labels.append(str(int(round(-val)))) print 'Plotting' fig = figure(figsize=(14, 24)) # ECCO2 gs1 = GridSpec(1, 2) gs1.update(left=0.1, right=0.95, bottom=0.7575, top=0.94, wspace=0.08) # Temperature ax = subplot(gs1[0, 0]) pcolor(ecco_lat, ecco_depth, ecco_temp, vmin=temp_min, vmax=temp_max, cmap='jet') # Overlay contour contour(ecco_lat, ecco_depth, ecco_temp, levels=[temp_contour], color='black') title(r'Temperature ($^{\circ}$C)', fontsize=24) ylabel('Depth (m)', fontsize=18) xlim([lat_min, lat_max]) ylim([depth_min, depth_max]) ax.set_xticks(lat_ticks) ax.set_xticklabels(lat_labels, fontsize=16) ax.set_yticks(depth_ticks) ax.set_yticklabels(depth_labels, fontsize=16) text(-64, 1000, 'a) ECCO2 initial conditions at ' + lon_string + ', January 1992', fontsize=28) # Salinity ax = subplot(gs1[0, 1]) pcolor(ecco_lat, ecco_depth, ecco_salt, vmin=salt_min, vmax=salt_max, cmap='jet') contour(ecco_lat, ecco_depth, ecco_salt, levels=[salt_contour], color='black') title('Salinity (psu)', fontsize=24) xlim([lat_min, lat_max]) ylim([depth_min, depth_max]) ax.set_xticks(lat_ticks) ax.set_xticklabels(lat_labels, fontsize=16) ax.set_yticks(depth_ticks) ax.set_yticklabels([]) # MetROMS gs2 = GridSpec(1, 2) gs2.update(left=0.1, right=0.95, bottom=0.525, top=0.7075, wspace=0.08) # Temperature ax = subplot(gs2[0, 0]) pcolor(roms_lat, roms_z, roms_temp, vmin=temp_min, vmax=temp_max, cmap='jet') contour(roms_lat, roms_z, roms_temp, levels=[temp_contour], color='black') ylabel('Depth (m)', fontsize=18) xlim([lat_min, lat_max]) ylim([depth_min, depth_max]) ax.set_xticks(lat_ticks) ax.set_xticklabels(lat_labels, fontsize=16) ax.set_yticks(depth_ticks) ax.set_yticklabels(depth_labels, fontsize=16) text(-49, 300, 'b) MetROMS, January 2016', fontsize=28) # Salinity ax = subplot(gs2[0, 1]) pcolor(roms_lat, roms_z, roms_salt, vmin=salt_min, vmax=salt_max, cmap='jet') contour(roms_lat, roms_z, roms_salt, levels=[salt_contour], color='black') xlim([lat_min, lat_max]) ylim([depth_min, depth_max]) ax.set_xticks(lat_ticks) ax.set_xticklabels(lat_labels, fontsize=16) ax.set_yticks(depth_ticks) ax.set_yticklabels([]) # FESOM low-res gs3 = GridSpec(1, 2) gs3.update(left=0.1, right=0.95, bottom=0.2925, top=0.475, wspace=0.08) # Temperature ax = subplot(gs3[0, 0]) img = PatchCollection(patches_lr, cmap='jet') img.set_array(array(fesom_temp_lr)) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) # Overlay contour on regular grid contour(lat_reg, depth_reg, temp_reg_lr, levels=[temp_contour], color='black') ylabel('Depth (m)', fontsize=18) xlim([lat_min, lat_max]) ylim([depth_min, depth_max]) ax.set_xticks(lat_ticks) ax.set_xticklabels(lat_labels, fontsize=16) ax.set_yticks(depth_ticks) ax.set_yticklabels(depth_labels, fontsize=16) text(-53, 300, 'c) FESOM (low-res), January 2016', fontsize=28) # Salinity ax = subplot(gs3[0, 1]) img = PatchCollection(patches_lr, cmap='jet') img.set_array(array(fesom_salt_lr)) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) contour(lat_reg, depth_reg, salt_reg_lr, levels=[salt_contour], color='black') xlim([lat_min, lat_max]) ylim([depth_min, depth_max]) ax.set_xticks(lat_ticks) ax.set_xticklabels(lat_labels, fontsize=16) ax.set_yticks(depth_ticks) ax.set_yticklabels([]) # FESOM high-res gs4 = GridSpec(1, 2) gs4.update(left=0.1, right=0.95, bottom=0.06, top=0.2425, wspace=0.08) # Temperature ax = subplot(gs4[0, 0]) img = PatchCollection(patches_hr, cmap='jet') img.set_array(array(fesom_temp_hr)) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) contour(lat_reg, depth_reg, temp_reg_hr, levels=[temp_contour], color='black') ylabel('Depth (m)', fontsize=18) xlim([lat_min, lat_max]) ylim([depth_min, depth_max]) ax.set_xticks(lat_ticks) ax.set_xticklabels(lat_labels, fontsize=16) ax.set_yticks(depth_ticks) ax.set_yticklabels(depth_labels, fontsize=16) text(-53, 300, 'd) FESOM (high-res), January 2016', fontsize=28) # Add a colorbar for temperature cbaxes = fig.add_axes([0.17, 0.015, 0.3, 0.015]) cbar = colorbar(img, orientation='horizontal', cax=cbaxes, extend='both', ticks=arange(temp_min, temp_max + 2, 2)) cbar.ax.tick_params(labelsize=16) # Salinity ax = subplot(gs4[0, 1]) img = PatchCollection(patches_hr, cmap='jet') img.set_array(array(fesom_salt_hr)) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) contour(lat_reg, depth_reg, salt_reg_hr, levels=[salt_contour], color='black') xlim([lat_min, lat_max]) ylim([depth_min, depth_max]) ax.set_xticks(lat_ticks) ax.set_xticklabels(lat_labels, fontsize=16) ax.set_yticks(depth_ticks) ax.set_yticklabels([]) # Add a colorbar for salinity cbaxes = fig.add_axes([0.6, 0.015, 0.3, 0.02]) cbar = colorbar(img, orientation='horizontal', cax=cbaxes, extend='both', ticks=arange(salt_min + 0.1, salt_max + 0.1, 0.2)) cbar.ax.tick_params(labelsize=16) fig.show() fig.savefig('ts_drift.png')
def zonal_ts_before_after(lon0, lat_min, lat_max, rcp, model, save=False, fig_name=None, season=None): # File paths mesh_path = '/short/y99/kaa561/FESOM/mesh/meshB/' if season is not None: file_beg = '/short/y99/kaa561/FESOM/highres_spinup/seasonal_climatology_oce_1996_2005.nc' file_end = '/short/y99/kaa561/FESOM/highres_spinup/seasonal_climatology_oce_2091_2100.nc' else: file_beg = '/short/y99/kaa561/FESOM/highres_spinup/annual_avg.oce.mean.1996.2005.nc' file_end = '/short/y99/kaa561/FESOM/rcp' + rcp + '_' + model + '/annual_avg.oce.mean.2091.2100.nc' # Figure out what to write on the title about longitude if lon0 < 0: lon_string = str(int(round(-lon0))) + r'$^{\circ}$W' else: lon_string = str(int(round(lon0))) + r'$^{\circ}$E' season_names = ['DJF', 'MAM', 'JJA', 'SON'] if season is not None: season_string = ', ' + season_names[season] else: season_string = '' print 'Building FESOM mesh' elm2D = fesom_grid(mesh_path) print 'Reading temperature and salinity data' if season is not None: t = season else: t = 0 id = Dataset(file_beg, 'r') temp_nodes_beg = id.variables['temp'][t, :] salt_nodes_beg = id.variables['salt'][t, :] id.close() id = Dataset(file_end, 'r') temp_nodes_end = id.variables['temp'][t, :] salt_nodes_end = id.variables['salt'][t, :] print 'Interpolating to ' + str(lon0) # Build arrays of SideElements making up zonal slices # Start with beginning selements_temp_beg = fesom_sidegrid(elm2D, temp_nodes_beg, lon0, lat_max) selements_salt_beg = fesom_sidegrid(elm2D, salt_nodes_beg, lon0, lat_max) # Build array of quadrilateral patches for the plots, and data values # corresponding to each SideElement patches = [] temp_beg = [] for selm in selements_temp_beg: # Make patch coord = transpose(vstack((selm.y, selm.z))) patches.append(Polygon(coord, True, linewidth=0.)) # Save data value temp_beg.append(selm.var) temp_beg = array(temp_beg) # Salinity has same patches but different values salt_beg = [] for selm in selements_salt_beg: salt_beg.append(selm.var) salt_beg = array(salt_beg) # Repeat for end selements_temp_end = fesom_sidegrid(elm2D, temp_nodes_end, lon0, lat_max) selements_salt_end = fesom_sidegrid(elm2D, salt_nodes_end, lon0, lat_max) temp_end = [] for selm in selements_temp_end: temp_end.append(selm.var) temp_end = array(temp_end) salt_end = [] for selm in selements_salt_end: salt_end.append(selm.var) salt_end = array(salt_end) # Find bounds on each variable temp_min = min(amin(temp_beg), amin(temp_end)) temp_max = max(amax(temp_beg), amax(temp_end)) salt_min = min(amin(salt_beg), amin(salt_end)) salt_max = max(amax(salt_beg), amax(salt_end)) # Find deepest depth # Start with 0 depth_min = 0 # Modify with patches for selm in selements_temp_beg: depth_min = min(depth_min, amin(selm.z)) # Round down to nearest 50 metres depth_min = floor(depth_min / 50) * 50 print 'Plotting' fig = figure(figsize=(16, 10)) # Temperature gs_temp = GridSpec(1, 2) gs_temp.update(left=0.11, right=0.9, bottom=0.5, top=0.9, wspace=0.05, hspace=0.5) # Beginning ax = subplot(gs_temp[0, 0]) img = PatchCollection(patches, cmap='jet') img.set_array(temp_beg) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title(r'Temperature ($^{\circ}$C), 1996-2005', fontsize=24) ax.set_xticklabels([]) ylabel('Depth (m)', fontsize=18) # End ax = subplot(gs_temp[0, 1]) img = PatchCollection(patches, cmap='jet') img.set_array(temp_end) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title(r'Temperature ($^{\circ}$C), 2091-2100', fontsize=24) ax.set_xticklabels([]) ax.set_yticklabels([]) # Add a colorbar on the right cbaxes = fig.add_axes([0.92, 0.55, 0.02, 0.3]) cbar = colorbar(img, cax=cbaxes, extend='both') cbar.ax.tick_params(labelsize=16) # Salinity gs_salt = GridSpec(1, 2) gs_salt.update(left=0.11, right=0.9, bottom=0.05, top=0.45, wspace=0.05, hspace=0.5) # Beginning ax = subplot(gs_salt[0, 0]) img = PatchCollection(patches, cmap='jet') img.set_array(salt_beg) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title('Salinity (psu), 1996-2005', fontsize=24) xlabel('Latitude', fontsize=18) ylabel('Depth (m)', fontsize=18) # End ax = subplot(gs_salt[0, 1]) img = PatchCollection(patches, cmap='jet') img.set_array(salt_end) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title('Salinity (psu), 2091-2100', fontsize=24) xlabel('Latitude', fontsize=18) ax.set_yticklabels([]) # Add a colorbar on the right cbaxes = fig.add_axes([0.92, 0.1, 0.02, 0.3]) cbar = colorbar(img, cax=cbaxes, extend='both') cbar.ax.tick_params(labelsize=16) # Main title suptitle('RCP ' + rcp[0] + '.' + rcp[1] + ' ' + model + ', ' + lon_string + season_string, fontsize=28) if save: fig.savefig(fig_name) else: fig.show()