def sst_sss_seasonal (mesh_path, file_path1, file_path2, save=False, fig_name=None): # FESOM parameters circumpolar=True mask_cavities=True # Season names for plot titles season_names = ['DJF', 'MAM', 'JJA', 'SON'] # Build FESOM mesh elements, patches = make_patches(mesh_path, circumpolar, mask_cavities) # Figure out how many 2D nodes there are file = open(mesh_path + 'nod2d.out', 'r') file.readline() n2d = 0 for line in file: n2d += 1 file.close() # Get seasonal averages of the 3D FESOM output temp = seasonal_avg(file_path1, file_path2, 'temp') salt = seasonal_avg(file_path1, file_path2, 'salt') # Select the surface layer sst = temp[:,:n2d] sss = salt[:,:n2d] # Plot fig = figure(figsize=(20,9)) # Loop over seasons for season in range(4): # SST # Build an array of FESOM data values corresponding to each Element values1 = [] for elm in elements: # For each element not in an ice shelf cavity, append the mean # value for the 3 component Nodes if not elm.cavity: values1.append(mean([sst[season,elm.nodes[0].id], sst[season,elm.nodes[1].id], sst[season,elm.nodes[2].id]])) ax = fig.add_subplot(2, 4, season+1, aspect='equal') img = PatchCollection(patches, cmap='RdBu_r' )#jet) img.set_array(array(values1)) #img.set_clim(vmin=-2, vmax=10) img.set_clim(vmin=-4, vmax=4) img.set_edgecolor('face') ax.add_collection(img) xlim([-35, 35]) ylim([-33, 37]) axis('off') if season == 0: text(-39, 0, r'SST ($^{\circ}$C)', fontsize=21, ha='right') title(season_names[season], fontsize=24) if season == 3: cbaxes1 = fig.add_axes([0.92, 0.55, 0.01, 0.3]) #cbar1 = colorbar(img, ticks=arange(-2,10+4,4), cax=cbaxes1) cbar1 = colorbar(img, ticks=arange(-4,4+2,2), cax=cbaxes1) cbar1.ax.tick_params(labelsize=16) # SSS values2 = [] for elm in elements: # For each element not in an ice shelf cavity, append the mean # value for the 3 component Nodes if not elm.cavity: values2.append(mean([sss[season,elm.nodes[0].id], sss[season,elm.nodes[1].id], sss[season,elm.nodes[2].id]])) ax = fig.add_subplot(2, 4, season+5, aspect='equal') img = PatchCollection(patches, cmap='RdBu_r') #jet) img.set_array(array(values2)) #img.set_clim(vmin=33, vmax=35) img.set_clim(vmin=-0.5, vmax=0.5) img.set_edgecolor('face') ax.add_collection(img) xlim([-35, 35]) ylim([-33, 37]) axis('off') if season == 0: text(-39, 0, 'SSS (psu)', fontsize=21, ha='right') if season == 3: cbaxes2 = fig.add_axes([0.92, 0.15, 0.01, 0.3]) #cbar2 = colorbar(img, ticks=arange(33,35+0.5,0.5), cax=cbaxes2) cbar2 = colorbar(img, ticks=arange(-0.5,0.5+0.25,0.25), cax=cbaxes2) cbar2.ax.tick_params(labelsize=16) # Decrease space between plots subplots_adjust(wspace=0.025,hspace=0.025) # Finished if save: fig.savefig(fig_name) else: fig.show()
def sose_fesom_seasonal(elements, file_path1, file_path2, var_name, lon0, depth_min, save=False, fig_name=None): # Path to SOSE seasonal climatology file sose_file = '/short/m68/kaa561/SOSE_seasonal_climatology.nc' lat_max = -60 #-30 season_names = ['DJF', 'MAM', 'JJA', 'SON'] # Bounds on colour scale if var_name == 'temp': var_min = -2.5 var_max = 3.5 #7.5 var_ticks = 1 elif var_name == 'salt': var_min = 33.8 var_max = 34.8 var_ticks = 0.2 else: print 'Unknown variable ' + var_name return # Choose what to write on the title about the variable if var_name == 'temp': var_string = r'Temperature ($^{\circ}$C)' elif var_name == 'salt': var_string = 'Salinity (psu)' # Choose what to write on the title about longitude if lon0 < 0: lon_string = ' at ' + str(int(round(-lon0))) + r'$^{\circ}$W' else: lon_string = ' at ' + str(int(round(lon0))) + r'$^{\circ}$E' print 'Processing SOSE data' # Read grid and 3D data (already seasonally averaged) id = Dataset(sose_file, 'r') lon_sose = id.variables['longitude'][0, :] lat_sose = id.variables['latitude'][:, 0] z_sose = id.variables['depth'][:] var_3d_sose = id.variables[var_name][:, :, :, :] # Calculate zonal slices for each season var_sose = ma.empty([4, size(z_sose), size(lat_sose, 0)]) var_sose[:, :, :] = 0.0 for season in range(4): print 'Calculating zonal slices for ' + season_names[season] var_sose[season, :, :] = interp_lon_sose(var_3d_sose[season, :, :, :], lon_sose, lon0) # Get seasonal averages of the FESOM output fesom_data = seasonal_avg(file_path1, file_path2, var_name) # Set colour levels lev = linspace(var_min, var_max, num=50) # Choose southern boundary based on extent of SOSE grid lat_min = amin(lat_sose) # Plot fig = figure(figsize=(20, 9)) for season in range(4): # FESOM print 'Calculating zonal slices for ' + season_names[season] patches, values, tmp = side_patches(elements, lat_max, lon0, fesom_data[season, :]) ax = fig.add_subplot(2, 4, season + 1) img = PatchCollection(patches, cmap=jet) img.set_array(array(values)) img.set_edgecolor('face') img.set_clim(vmin=var_min, vmax=var_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title('FESOM (' + season_names[season] + ')', fontsize=24) if season == 0: ylabel('depth (m)', fontsize=18) # SOSE fig.add_subplot(2, 4, season + 5) pcolormesh(lat_sose, z_sose, var_sose[season, :, :], vmin=var_min, vmax=var_max, cmap='jet') xlim([lat_min, lat_max]) ylim([depth_min, 0]) title('SOSE (' + season_names[season] + ')', fontsize=24) xlabel('Latitude', fontsize=18) if season == 0: ylabel('depth (m)', fontsize=18) # Add colorbar cbaxes = fig.add_axes([0.93, 0.2, 0.015, 0.6]) cbar = colorbar(img, cax=cbaxes, ticks=arange(var_min, var_max + var_ticks, var_ticks)) cbar.ax.tick_params(labelsize=16) # Add the main title suptitle(var_string + lon_string, fontsize=30) # Finished if save: fig.savefig(fig_name) else: fig.show()
def aice_hi_seasonal(mesh_path, file_path1, file_path2, save=False, fig_name=None): # FESOM parameters circumpolar = True mask_cavities = True # Season names for plot titles season_names = ['DJF', 'MAM', 'JJA', 'SON'] # Build FESOM mesh elements, patches = make_patches(mesh_path, circumpolar, mask_cavities) # Get seasonal averages of the FESOM output aice = seasonal_avg(file_path1, file_path2, 'area') hi = seasonal_avg(file_path1, file_path2, 'hice') # Plot fig = figure(figsize=(20, 9)) # Loop over seasons for season in range(4): # aice # Build an array of FESOM data values corresponding to each Element values1 = [] for elm in elements: # For each element not in an ice shelf cavity, append the mean # value for the 3 component Nodes if not elm.cavity: values1.append( mean([ aice[season, elm.nodes[0].id], aice[season, elm.nodes[1].id], aice[season, elm.nodes[2].id] ])) ax = fig.add_subplot(2, 4, season + 1, aspect='equal') img = PatchCollection(patches, cmap=jet) img.set_array(array(values1)) #img.set_clim(vmin=-1, vmax=1) img.set_clim(vmin=0, vmax=1) img.set_edgecolor('face') ax.add_collection(img) xlim([-35, 35]) ylim([-33, 37]) axis('off') if season == 0: text(-39, 0, 'aice (%)', fontsize=21, ha='right') title(season_names[season], fontsize=24) if season == 3: cbaxes1 = fig.add_axes([0.92, 0.55, 0.01, 0.3]) #cbar1 = colorbar(img, ticks=arange(-1,1+0.5,0.5), cax=cbaxes1) cbar1 = colorbar(img, ticks=arange(0, 1 + 0.25, 0.25), cax=cbaxes1) cbar1.ax.tick_params(labelsize=16) # hi values2 = [] for elm in elements: # For each element not in an ice shelf cavity, append the mean # value for the 3 component Nodes if not elm.cavity: values2.append( mean([ hi[season, elm.nodes[0].id], hi[season, elm.nodes[1].id], hi[season, elm.nodes[2].id] ])) ax = fig.add_subplot(2, 4, season + 5, aspect='equal') img = PatchCollection(patches, cmap=jet) img.set_array(array(values2)) #img.set_clim(vmin=-0.5, vmax=0.5) img.set_clim(vmin=0, vmax=1.5) img.set_edgecolor('face') ax.add_collection(img) xlim([-35, 35]) ylim([-33, 37]) axis('off') if season == 0: text(-39, 0, 'hi (m)', fontsize=21, ha='right') if season == 3: cbaxes2 = fig.add_axes([0.92, 0.15, 0.01, 0.3]) #cbar2 = colorbar(img, ticks=arange(-0.5,0.5+0.25,0.25), cax=cbaxes2) cbar2 = colorbar(img, ticks=arange(0, 1.5 + 0.5, 0.5), cax=cbaxes2) cbar2.ax.tick_params(labelsize=16) # Decrease space between plots subplots_adjust(wspace=0.025, hspace=0.025) # Finished if save: fig.savefig(fig_name) else: fig.show()
def nsidc_aice_seasonal(mesh_path, file_path1, file_path2, save=False, fig_name=None): # FESOM parameters circumpolar = True mask_cavities = True # Season names for plot titles season_names = ['DJF', 'MAM', 'JJA', 'SON'] # NSIDC file paths nsidc_head = '/short/m68/kaa561/nsidc_aice/seaice_conc_monthly_sh' nsidc_head_0 = nsidc_head + '_f11_' nsidc_head_1 = nsidc_head + '_f13_' nsidc_tail = '_v02r00.nc' # Degrees to radians conversion factor deg2rad = pi / 180.0 # Number of days per month (just for NSIDC) ndays_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] # Build FESOM mesh elements, patches = make_patches(mesh_path, circumpolar, mask_cavities) # Get seasonal averages of the FESOM output fesom_data = seasonal_avg(file_path1, file_path2, 'area') # Read NSIDC grid from the January file id = Dataset(nsidc_head_0 + '199501' + nsidc_tail, 'r') nsidc_lon = id.variables['longitude'][:, :] nsidc_lat = id.variables['latitude'][:, :] id.close() # Initialise seasonal averages of NSIDC data nsidc_data = ma.empty([4, size(nsidc_lon, 0), size(nsidc_lon, 1)]) nsidc_data[:, :] = 0.0 # Process one season at a time for season in range(4): # Figure out which months we care about if season == 0: # DJF nsidc_months = [12, 1, 2] elif season == 1: # MAM nsidc_months = [3, 4, 5] elif season == 2: # JJA nsidc_months = [6, 7, 8] elif season == 3: # SON nsidc_months = [9, 10, 11] season_days = 0 # Number of days in season; this will be incremented # Process one month at a time for month in nsidc_months: # Construct NSIDC file path if month < 10: nsidc_file = nsidc_head_0 + '19950' + str(month) + nsidc_tail else: nsidc_file = nsidc_head_1 + '1995' + str(month) + nsidc_tail # Read concentration data id = Dataset(nsidc_file, 'r') nsidc_data_raw = id.variables['seaice_conc_monthly_cdr'][0, :, :] # Read std just for the mask nsidc_mask = id.variables['stdev_of_seaice_conc_monthly_cdr'][ 0, :, :] id.close() # Set land mask nsidc_data_tmp = ma.empty(shape(nsidc_data_raw)) nsidc_data_tmp[:, :] = 0.0 nsidc_data_tmp[~nsidc_mask.mask] = nsidc_data_raw[~nsidc_mask.mask] nsidc_data_tmp[nsidc_mask.mask] = ma.masked # Accumulate master array, weighted with number of days per month nsidc_data[season, :, :] += nsidc_data_tmp * ndays_month[month - 1] season_days += ndays_month[month - 1] # Convert from sum to average nsidc_data[season, :, :] /= season_days # Convert to spherical coordinates nsidc_x = -(nsidc_lat + 90) * cos(nsidc_lon * deg2rad + pi / 2) nsidc_y = (nsidc_lat + 90) * sin(nsidc_lon * deg2rad + pi / 2) # Find boundaries for each side of plot based on extent of NSIDC grid bdry1 = amax(nsidc_x[:, 0]) bdry2 = amin(nsidc_x[:, -1]) bdry3 = amin(nsidc_y[:, 0]) bdry4 = amax(nsidc_y[:, -1]) # Set consistent colour levels lev = linspace(0, 1, num=50) # Plot fig = figure(figsize=(20, 9)) # Loop over seasons for season in range(4): # NSIDC ax = fig.add_subplot(2, 4, season + 1, aspect='equal') contourf(nsidc_x, nsidc_y, nsidc_data[season, :, :], lev) if season == 0: text(-39, 0, 'NSIDC', fontsize=24, ha='right') title(season_names[season], fontsize=24) xlim([bdry1, bdry2]) ylim([bdry3, bdry4]) axis('off') # Build an array of FESOM data values corresponding to each Element values = [] for elm in elements: # For each element not in an ice shelf cavity, append the mean # value for the 3 component Nodes if not elm.cavity: values.append( mean([ fesom_data[season, elm.nodes[0].id], fesom_data[season, elm.nodes[1].id], fesom_data[season, elm.nodes[2].id] ])) # Plot FESOM data ax = fig.add_subplot(2, 4, season + 5, aspect='equal') img = PatchCollection(patches, cmap=jet) img.set_array(array(values)) img.set_clim(vmin=0, vmax=1) img.set_edgecolor('face') ax.add_collection(img) xlim([bdry1, bdry2]) ylim([bdry3, bdry4]) axis('off') if season == 0: text(-39, 0, 'FESOM', fontsize=24, ha='right') # Add a horizontal colorbar at the bottom cbaxes = fig.add_axes([0.25, 0.04, 0.5, 0.02]) cbar = colorbar(img, orientation='horizontal', ticks=arange(0, 1 + 0.25, 0.25), cax=cbaxes) cbar.ax.tick_params(labelsize=16) # Add the main title suptitle('Sea ice concentration', fontsize=30) # Decrease space between plots subplots_adjust(wspace=0.025, hspace=0.025) # Finished if save: fig.savefig(fig_name) else: fig.show()
def mld_jja_diff(mesh_path, file_path_beg, file_path_end, save=False, fig_name=None, limit=None): # Definition of mixed layer depth: where potential density exceeds # surface density by this amount (kg/m^3) as in Sallee et al 2013 density_anom = 0.03 # Plotting parameters circumpolar = True mask_cavities = True lat_max = -30 + 90 font_sizes = [30, 24, 20] print 'Building grid' elements, patches = make_patches(mesh_path, circumpolar, mask_cavities) print 'Reading data' # First 10 years # Read temperature and salinity at each node, seasonally averaged over JJA tmp = seasonal_avg(file_path_beg, file_path_beg, 'temp') temp_beg = tmp[2, :] tmp = seasonal_avg(file_path_beg, file_path_beg, 'salt') salt_beg = tmp[2, :] # Last 10 years tmp = seasonal_avg(file_path_beg, file_path_end, 'temp') temp_end = tmp[2, :] tmp = seasonal_avg(file_path_beg, file_path_end, 'salt') salt_end = tmp[2, :] # Calculate potential density (depth 0) print 'Calculating density' density_beg = unesco(temp_beg, salt_beg, zeros(shape(temp_beg))) density_end = unesco(temp_end, salt_end, zeros(shape(temp_end))) # Calculate mixed layer depth at each element print 'Calculating mixed layer depth' # First 10 years mld_beg = [] for elm in elements: if (mask_cavities and not elm.cavity) or (not mask_cavities): # Get mixed layer depth at each node mld_nodes = [] # Make sure we exclude ice shelf cavity nodes from element mean # (an Element can be a non-cavity element and still have up to 2 # cavity nodes) for i in range(3): if (mask_cavities and not elm.cavity_nodes[i]) or (not mask_cavities): node = elm.nodes[i] density_sfc = density_beg[node.id] temp_depth = node.depth curr_node = node.below while True: if curr_node is None: # Reached bottom mld_nodes.append(temp_depth) break if density_beg[ curr_node.id] >= density_sfc + density_anom: # Reached critical density anomaly mld_nodes.append(curr_node.depth) break temp_depth = curr_node.depth curr_node = curr_node.below # For this element, save the mean mixed layer depth across # non-cavity nodes (up to 3) mld_beg.append(mean(array(mld_nodes))) # Last 10 years mld_end = [] for elm in elements: if (mask_cavities and not elm.cavity) or (not mask_cavities): # Get mixed layer depth at each node mld_nodes = [] # Make sure we exclude ice shelf cavity nodes from element mean # (an Element can be a non-cavity element and still have up to 2 # cavity nodes) for i in range(3): if (mask_cavities and not elm.cavity_nodes[i]) or (not mask_cavities): node = elm.nodes[i] density_sfc = density_end[node.id] temp_depth = node.depth curr_node = node.below while True: if curr_node is None: mld_nodes.append(temp_depth) break if density_end[ curr_node.id] >= density_sfc + density_anom: mld_nodes.append(curr_node.depth) break temp_depth = curr_node.depth curr_node = curr_node.below # For this element, save the mean mixed layer depth across # non-cavity nodes (up to 3) mld_end.append(mean(array(mld_nodes))) # Calculate change in mixed layer depth mld_change = array(mld_end) - array(mld_beg) if mask_cavities: # Get mask array of patches for ice shelf cavity elements mask_patches = iceshelf_mask(elements) # Choose colour bounds if limit is not None: bound = limit else: bound = amax(array(mld_change)) print 'Plotting' # Set up plot fig = figure(figsize=(16, 12)) ax = fig.add_subplot(1, 1, 1, aspect='equal') # Set colourmap for patches, and refer it to the values array img = PatchCollection(patches, cmap='RdBu_r') img.set_array(array(mld_change)) img.set_edgecolor('face') # Add patches to plot ax.add_collection(img) if mask_cavities: # Set colour to light grey for patches in mask overlay = PatchCollection(mask_patches, facecolor=(0.6, 0.6, 0.6)) overlay.set_edgecolor('face') # Add mask to plot ax.add_collection(overlay) # Configure plot xlim([-lat_max, lat_max]) ylim([-lat_max, lat_max]) ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) axis('off') title('Change in JJA mixed layer depth (m)\n2091-2100 vs 2006-2015', fontsize=font_sizes[0]) cbar = colorbar(img) cbar.ax.tick_params(labelsize=font_sizes[2]) img.set_clim(vmin=-bound, vmax=bound) if save: fig.savefig(fig_name) else: fig.show()
def temp_salt_seasonal (elements, file_path1, file_path2, lon0, depth_min, save=False, fig_name=None): # Northern boundary for plot lat_max = -30 # Season names for titles season_names = ['DJF', 'MAM', 'JJA', 'SON'] # Bounds on colour scales for temperature and salinity var_min = [-2.5, 33.8] var_max = [3.5, 34.8] var_ticks = [1, 0.2] # Choose 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' # Get seasonal averages of temperature and salinity temp_data = seasonal_avg(file_path1, file_path2, 'temp') salt_data = seasonal_avg(file_path1, file_path2, 'salt') # Set colour levels lev1 = linspace(var_min[0], var_max[0], num=50) lev2 = linspace(var_min[1], var_max[1], num=50) # Plot fig = figure(figsize=(20,9)) # Loop over seasons for season in range(4): print 'Calculating zonal slices for ' + season_names[season] # Interpolate temperature to lon0 and get plotting patches patches, values, lat_min = side_patches(elements, lat_max, lon0, temp_data[season,:]) ax = fig.add_subplot(2, 4, season+1) img = PatchCollection(patches, cmap=jet) img.set_array(array(values)) img.set_edgecolor('face') img.set_clim(vmin=var_min[0], vmax=var_max[0]) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title('Temperature (' + season_names[season] + ')', fontsize=24) if season == 0: # Add depth label on the left ylabel('depth (m)', fontsize=18) if season == 3: # Add a colourbar on the right cbaxes = fig.add_axes([0.93, 0.6, 0.015, 0.3]) cbar1 = colorbar(img, cax=cbaxes, ticks=arange(var_min[0], var_max[0]+var_ticks[0], var_ticks[0])) cbar1.ax.tick_params(labelsize=16) # Repeat for salinity patches, values, lat_min = side_patches(elements, lat_max, lon0, salt_data[season,:]) ax = fig.add_subplot(2, 4, season+5) img = PatchCollection(patches, cmap=jet) img.set_array(array(values)) img.set_edgecolor('face') img.set_clim(vmin=var_min[1], vmax=var_max[1]) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title('Salinity (' + season_names[season] + ')', fontsize=24) if season == 0: ylabel('Depth (m)', fontsize=18) xlabel('Latitude', fontsize=18) if season == 3: cbaxes = fig.add_axes([0.93, 0.1, 0.015, 0.3]) cbar2 = colorbar(img, cax=cbaxes, ticks=arange(var_min[1], var_max[1]+var_ticks[1], var_ticks[1])) cbar2.ax.tick_params(labelsize=16) suptitle(lon_string, fontsize=30) # Finished if save: fig.savefig(fig_name) else: fig.show()
def ismr_seasonal (mesh_path, file_path1, file_path2, save=False, fig_name=None): # Plotting parameters lat_max = -63 + 90 circumpolar = True mask_cavities = True # Seconds per year sec_per_year = 365.25*24*3600 # Season names for plot titles season_names = ['DJF', 'MAM', 'JJA', 'SON'] # Set colour map # Values for change points cmap_vals = array([-0.1, 0, 1, 2, 5, 8]) # Colours for change points # (blue, white, yellow-orange, red-orange, dark red, purple) cmap_colors = [(0.26, 0.45, 0.86), (1, 1, 1), (1, 0.9, 0.4), (0.99, 0.59, 0.18), (0.5, 0.0, 0.08), (0.96, 0.17, 0.89)] # Map to 0-1 cmap_vals_norm = (cmap_vals + 0.1)/(8 + 0.1) # Combine into a list cmap_list = [] for i in range(size(cmap_vals)): cmap_list.append((cmap_vals_norm[i], cmap_colors[i])) # Make colour map mf_cmap = LinearSegmentedColormap.from_list('melt_freeze', cmap_list) # Build FESOM mesh # Get separate patches for the open ocean elements so we can mask them out elements, mask_patches = make_patches(mesh_path, circumpolar, mask_cavities) patches = iceshelf_mask(elements) # Get seasonal averages of freshwater flux ismr = seasonal_avg(file_path1, file_path2, 'wnet')*sec_per_year # Select ice shelf nodes values = [] # Set up a grey square covering the domain, anything that isn't covered # up later is land x_reg, y_reg = meshgrid(linspace(-lat_max, lat_max, num=100), linspace(-lat_max, lat_max, num=100)) land_square = zeros(shape(x_reg)) # Plot fig = figure(figsize=(20,6)) # Loop over seasons for season in range(4): # Build an array of ismr values corresponding to each ice shelf Element values = [] # Loop over elements for elm in elements: # For each element in an ice shelf cavity, append the mean value # for the 3 component Nodes if elm.cavity: values.append(mean([ismr[season,elm.nodes[0].id], ismr[season,elm.nodes[1].id], ismr[season,elm.nodes[2].id]])) ax = fig.add_subplot(1, 4, season+1, aspect='equal') # Start with grey square background for land contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) img = PatchCollection(patches, cmap='RdBu_r') #mf_cmap) img.set_array(array(values)) img.set_edgecolor('face') img.set_clim(vmin=-3, vmax=3) #img.set_clim(vmin=-0.1, vmax=8) ax.add_collection(img) # Mask out the open ocean in white overlay = PatchCollection(mask_patches, facecolor=(1,1,1)) overlay.set_edgecolor('face') ax.add_collection(overlay) # Contour ice shelf fronts contour_lines = [] for elm in elements: # Select elements where exactly 2 of the 3 nodes are in a cavity if count_nonzero(elm.cavity_nodes) == 2: # Save the coastal flags and x- and y- coordinates of these 2 coast_tmp = [] x_tmp = [] y_tmp = [] for i in range(3): if elm.cavity_nodes[i]: coast_tmp.append(elm.coast_nodes[i]) x_tmp.append(elm.x[i]) y_tmp.append(elm.y[i]) # Select elements where at most 1 of these 2 nodes are coastal if count_nonzero(coast_tmp) < 2: # Draw a line between the 2 nodes contour_lines.append([(x_tmp[0], y_tmp[0]), (x_tmp[1], y_tmp[1])]) # Add all the lines to the plot contours = LineCollection(contour_lines, edgecolor='black', linewidth=1) ax.add_collection(contours) # Configure plot xlim([-lat_max, lat_max]) ylim([-lat_max, lat_max]) axis('off') title(season_names[season], fontsize=24) if season == 3: cbaxes = fig.add_axes([0.92, 0.2, 0.01, 0.6]) cbar = colorbar(img, cax=cbaxes) cbar.ax.tick_params(labelsize=16) suptitle('Ice shelf melt rate (m/y)', fontsize=30) # Decrease space between plots subplots_adjust(wspace=0.025) # Finished if save: fig.savefig(fig_name) else: fig.show()