Definition of Key Frontal Areas¶

Author: Kai Yang

Manuscript: Global trends in ocean fronts: impacts on air-sea CO2 flux and chlorophyll concentrations

Creation date: 2024-May-18

Latest update: 2025-Jun-03

This Jupyter notebook produces Fig. 6 of the manuscript.

In [1]:
# Import libraries
import xarray as xr
# import cmocean as cm
import cartopy.crs as ccrs
import geopandas as gpd
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import ticker
import matplotlib.ticker as mticker
import pylab as plt
import numpy as np
# Inline plotting
%matplotlib inline
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
/Users/kyang7/anaconda3/lib/python3.11/site-packages/pandas/core/arrays/masked.py:60: UserWarning: Pandas requires version '1.3.6' or newer of 'bottleneck' (version '1.3.5' currently installed).
  from pandas.core import (
In [2]:
from utils import area,ccrs_land,add_patches
In [3]:
# read climatologies of frontal metrics

# MODIS
data_set = xr.open_dataset('../datasets/maps/frontalDensity_overall_annual_percentages.nc',chunks={'lat':10,'lon':10})
Fdens = data_set.frontalDensity_mean_percentage

data_set = xr.open_dataset('../datasets/maps/frontalFrequency_overall_annual_percentages.nc',chunks={'lat':10,'lon':10})
Ffreq = data_set.frontalFrequency_mean_percentage

data_set = xr.open_dataset('../datasets/maps/frontalStrength_overall_annual_percentages.nc',chunks={'lat':10,'lon':10})
Fstre = data_set.frontalStrength_mean_percentage





Fdens[1:30,:] = np.nan
Fdens[150:180,:] = np.nan
Ffreq[1:30,:] = np.nan
Ffreq[150:180,:] = np.nan
Fstre[1:30,:] = np.nan
Fstre[150:180,:] = np.nan

Fdens_xr = Fdens
Ffreq_xr = Ffreq
Fstre_xr = Fstre


# # ESACCI
# data_set1 = xr.open_dataset('../datasets/maps/ESACCI_front_metrics_climatologies_trends.nc',chunks={'lat':10,'lon':10})
# Fdens1 = data_set1.Fdens_mean
# Ffreq1 = data_set1.Ffreq_mean
# Fstre1 = data_set1.Fstre_mean
# Fdens1_xr = Fdens1
# Ffreq1_xr = Ffreq1
# Fstre1_xr = Fstre1
In [4]:
# lat_1deg = np.arange(-89.5, 90.5, 1)  # Center points of 1° bins
# lon_1deg = np.arange(-179.5, 180.5, 1)

# cos_lat_1deg = np.cos(np.radians(lat_1deg))[:, np.newaxis]

# Fdens = Fdens*cos_lat_1deg
# Ffreq = Ffreq*cos_lat_1deg
# Fstre = Fstre*cos_lat_1deg

# Fdens_xr = Fdens
# Ffreq_xr = Ffreq
# Fstre_xr = Fstre
In [5]:
# read shapefiles of the 80th percentiles contours of frontal metrics
Fdens_perc = gpd.read_file(r'../datasets/shapefiles/Fdens_p80_polygons.shp')
Ffreq_perc = gpd.read_file(r'../datasets/shapefiles/Ffreq_p80_polygons.shp')
Fstre_perc = gpd.read_file(r'../datasets/shapefiles/Fstre_p80_polygons.shp')
In [6]:
fig = plt.figure(figsize=(30, 15),dpi=600)

plt.rcParams['figure.figsize'] = [30, 15]

fig, axs = plt.subplots(nrows=4,ncols=1,
                        subplot_kw={'projection': ccrs.Robinson(central_longitude=180)})
#################################################################################################################################################
#################################################################################################################################################
#################################################################################################################################################
# Panel b
# mapping
axs[0] = fig.add_subplot(4, 1, 1, projection = ccrs.Robinson(central_longitude=180))


im1 = Fdens.plot(ax=axs[0], transform = ccrs.PlateCarree(), add_colorbar=False, 
                 cmap = 'Oranges', rasterized=True,vmin = 0, vmax = 50) 

plt.plot([0, 360], [60.1, 60.1],
         color='black', linewidth=1, linestyle='--', markersize=3,
         # Be explicit about which transform you want:
         transform = ccrs.PlateCarree())
plt.plot([0, 360], [-60.1, -60.1],
         color='black', linewidth=1, linestyle='--', markersize=3,
         # Be explicit about which transform you want:
         transform = ccrs.PlateCarree())

# contours
Fdens_perc.plot(transform=ccrs.PlateCarree(),edgecolor='k', facecolor="None", linewidth=1, linestyle = "-", alpha=1, ax = axs[0])



# map settings
axs[0].set_extent([0.1,359.99,-85, 85], crs=ccrs.PlateCarree())
axs[0].add_feature(ccrs_land)
add_patches(axs[0])
axs[0].set_title("b  Frontal density",fontsize=15, fontweight = "bold",loc = 'left',fontname = 'Arial')
gl = axs[0].gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
                  linewidth=0.5, color='gray', alpha=0.0, linestyle='--')
gl.xlabels_top = False
gl.ylabels_right = False
gl.xlabel_style = {'size': 12, 'color': 'k','name': 'Arial'}
gl.ylabel_style = {'size': 12, 'color': 'k','name': 'Arial'}

# colorbar
cbar_ax = fig.add_axes([0.61, 0.7226, 0.005, 0.15])
cbar=fig.colorbar(im1, cax=cbar_ax,orientation='vertical',extend='both')
cbar.set_label('Density (%)', rotation=90, fontsize=12,fontname = 'Arial')
cbar.ax.tick_params(labelsize=11)
for l in cbar.ax.yaxis.get_ticklabels():
    l.set_family("Arial")
# cbar.ax.plot([0, 1], [13.06,13.06], 'k') #unweighted
cbar.ax.plot([0, 1],[13.5329, 13.5329],'k') #weighted
#################################################################################################################################################
#################################################################################################################################################
#################################################################################################################################################
# Panel d
axs[1] = fig.add_subplot(4, 1, 2, projection = ccrs.Robinson(central_longitude=180))

# mapping
im1 = Ffreq.plot(ax=axs[1], transform = ccrs.PlateCarree(), add_colorbar=False,
                   cmap = 'Oranges', 
                   rasterized=True,vmin = -1, vmax = 50) 

# contours
Ffreq_perc.plot(transform=ccrs.PlateCarree(),edgecolor='k', facecolor="None", linewidth=1, linestyle = "-", alpha=1, ax = axs[1])


plt.plot([0, 360], [60.1, 60.1],
         color='black', linewidth=1, linestyle='--', markersize=3,
         # Be explicit about which transform you want:
         transform = ccrs.PlateCarree())
plt.plot([0, 360], [-60.1, -60.1],
         color='black', linewidth=1, linestyle='--', markersize=3,
         # Be explicit about which transform you want:
         transform = ccrs.PlateCarree())

# map settings
axs[1].set_extent([0.1,359.99,-85, 85], crs=ccrs.PlateCarree())
axs[1].add_feature(ccrs_land)
add_patches(axs[1])
axs[1].set_title("d  Frontal frequency",fontsize=15, fontweight = "bold",loc = 'left',fontname = 'Arial')
gl = axs[1].gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
                  linewidth=0.5, color='gray', alpha=0.0, linestyle='--')
gl.xlabels_top = False
gl.ylabels_right = False
# gl.ylocator = mticker.FixedLocator([-80, -60, -40, -20, 0, 20, 40, 60, 80])
gl.xlabel_style = {'size': 12, 'color': 'k','name': 'Arial'}
gl.ylabel_style = {'size': 12, 'color': 'k','name': 'Arial'}

# colorbar
cbar_ax = fig.add_axes([0.61, 0.5217, 0.005, 0.15])
cbar=fig.colorbar(im1, cax=cbar_ax,orientation='vertical',extend='both')
cbar.set_label('Frequency (%)', rotation=90, fontsize=12,fontname = 'Arial')
cbar.ax.tick_params(labelsize=11)
for l in cbar.ax.yaxis.get_ticklabels():
    l.set_family("Arial")
# cbar.ax.plot([0, 1], [13.06,13.06], 'k') #unweighted
cbar.ax.plot([0, 1],[12.2053, 12.2053],'k') #weighted

#################################################################################################################################################
#################################################################################################################################################
#################################################################################################################################################
# Panel d
axs[2] = fig.add_subplot(4, 1, 3, projection = ccrs.Robinson(central_longitude=180))

# mapping
im1 = Fstre.plot(ax=axs[2], transform = ccrs.PlateCarree(), add_colorbar=False,
                   cmap = 'Oranges', 
                   rasterized=True,vmin = 0.05, vmax = 0.1) 

# contours
Fstre_perc.plot(transform=ccrs.PlateCarree(),edgecolor='k', facecolor="None", linewidth=1, linestyle = "-", alpha=1, ax = axs[2])


plt.plot([0, 360], [60.1, 60.1],
         color='black', linewidth=1, linestyle='--', markersize=3,
         # Be explicit about which transform you want:
         transform = ccrs.PlateCarree())
plt.plot([0, 360], [-60.1, -60.1],
         color='black', linewidth=1, linestyle='--', markersize=3,
         # Be explicit about which transform you want:
         transform = ccrs.PlateCarree())

# map settings
axs[2].set_extent([0.1,359.99,-85, 85], crs=ccrs.PlateCarree())
axs[2].add_feature(ccrs_land)
add_patches(axs[2])
axs[2].set_title("f  Frontal strength",fontsize=15, fontweight = "bold",loc = 'left', fontname = 'Arial')
gl = axs[2].gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
                  linewidth=0.5, color='gray', alpha=0.0, linestyle='--')
gl.xlabels_top = False
gl.ylabels_right = False
gl.xlabel_style = {'size': 12, 'color': 'k','name': 'Arial'}
gl.ylabel_style = {'size': 12, 'color': 'k','name': 'Arial'}

# colorbar
cbar_ax = fig.add_axes([0.61, 0.3209, 0.005, 0.15])
cbar=fig.colorbar(im1, cax=cbar_ax,orientation='vertical',extend='both')
cbar.set_label('Strength ($\u00b0$C km$^{-1}$)', rotation=90, fontsize=12, fontname = 'Arial')
cbar.ax.tick_params(labelsize=11)
for l in cbar.ax.yaxis.get_ticklabels():
    l.set_family("Arial")
# cbar.ax.plot([0, 1], [4.24,4.24], 'k') #unweighted
cbar.ax.plot([0,1],[0.0606,0.0606],'k') #weighted

axs[2].text(0.5, -0.17, 'Longitude', va='bottom', ha='center',
        rotation='horizontal', rotation_mode='anchor', fontweight = 'bold',
        transform=axs[2].transAxes, fontname = 'Arial', fontsize = 12)
#################################################################################################################################################
#################################################################################################################################################
#################################################################################################################################################
# Panel a
ax_w1 = plt.axes([0.36, 0.7126, 0.05, 0.167])

# calculate and plot zonal mean values
# MODIS
zonal_mean_fdens=Fdens_xr.mean(axis = 1)
y = data_set.lat
pos=np.ma.masked_where(zonal_mean_fdens<0, zonal_mean_fdens)
ax_w1.fill_betweenx(y, pos*0, pos, color='#F6944B',linewidth = 1)

plt.plot([0,30], [-60.1, -60.1],
         color='black', linewidth=1, linestyle='--', markersize=3)
plt.plot([0,30], [60.1, 60.1],
         color='black', linewidth=1, linestyle='--', markersize=3)

# plot settings
ax_w1.set_xlim(0,30)
ax_w1.xaxis.set_label_coords(0.5, -0.12)
ax_w1.xaxis.set_major_locator(plt.MaxNLocator(2))
ax_w1.tick_params(axis='both', which='major', labelsize=10, pad = 0.5)
ax_w1.set_yticks(range(-60,61,20))
ax_w1.set_yticklabels(['60$\u00b0$S','40$\u00b0$S','20$\u00b0$S','0$\u00b0$','20$\u00b0$N','40$\u00b0$N','60$\u00b0$N'],fontname = 'Arial',fontsize = 12)
ax_w1.set_ylim(-80,80)
ax_w1.set_xlabel('%',fontname = 'Arial',fontsize = 12)
ax_w1.xaxis.set_label_coords(0.5, -0.09)
ax_w1.set_ylabel('Latitude',fontname = 'Arial',fontsize = 12,fontweight = "bold")
ax_w1.set_xticks([0, 10, 20, 30])
ax_w1.set_xticklabels([0, 10, 20, 30],fontname = 'Arial',fontsize = 12)
ax_w1.set_xticks(range(0,31,10))
ax_w1.text(-15,90,'a',fontsize=15, fontweight = "bold",fontname = 'Arial')
#################################################################################################################################################
#################################################################################################################################################
#################################################################################################################################################
# Panel c
ax_w2 = plt.axes([0.36, 0.5126, 0.05, 0.167])

# calculate and plot zonal mean values
# MODIS
zonal_mean_ffreq=Ffreq_xr.mean(axis = 1)
y = data_set.lat
pos=np.ma.masked_where(zonal_mean_ffreq<0, zonal_mean_ffreq)
ax_w2.fill_betweenx(y, pos*0, pos, color='#F6944B',linewidth = 1)

plt.plot([0,30], [-60.1, -60.1],
         color='black', linewidth=1, linestyle='--', markersize=3)
plt.plot([0,30], [60.1, 60.1],
         color='black', linewidth=1, linestyle='--', markersize=3)
# plot settings
ax_w2.set_xlim(0,30)
ax_w2.xaxis.set_label_coords(0.5, -0.12)
ax_w2.xaxis.set_major_locator(plt.MaxNLocator(2))
ax_w2.tick_params(axis='both', which='major', labelsize=10, pad = 0.5)
ax_w2.set_yticks(range(-60,61,20))
ax_w2.set_yticklabels(['60$\u00b0$S','40$\u00b0$S','20$\u00b0$S','0$\u00b0$','20$\u00b0$N','40$\u00b0$N','60$\u00b0$N'],fontname = 'Arial',fontsize = 12)
ax_w2.set_ylim(-80,80)
ax_w2.set_xlabel('%',fontname = 'Arial',fontsize = 12)
ax_w2.xaxis.set_label_coords(0.5, -0.09)
ax_w2.set_ylabel('Latitude',fontname = 'Arial',fontsize = 12,fontweight = "bold")
ax_w2.set_xticks([0, 10, 20, 30])
ax_w2.set_xticklabels([0, 10, 20, 30],fontname = 'Arial',fontsize = 12)
ax_w2.set_xticks(range(0,31,10))
ax_w2.text(-15,90,'c',fontsize=15, fontweight = "bold",fontname = 'Arial')
#################################################################################################################################################
#################################################################################################################################################
#################################################################################################################################################
# Panel e
ax_w3 = plt.axes([0.36, 0.3126, 0.05, 0.167])

# calculate and plot zonal mean values
# MODIS
zonal_mean_fstre=Fstre_xr.mean(axis = 1)
y = data_set.lat
pos=np.ma.masked_where(zonal_mean_fstre<0, zonal_mean_fstre)
ax_w3.fill_betweenx(y, pos*0, pos, color='#F6944B',linewidth = 1)

plt.plot([0,30], [-60.1, -60.1],
         color='black', linewidth=1, linestyle='--', markersize=3)
plt.plot([0,30], [60.1, 60.1],
         color='black', linewidth=1, linestyle='--', markersize=3)

# plot settings
ax_w3.set_xlim(0,0.15)
ax_w3.xaxis.set_label_coords(0.5, -0.12)
ax_w3.xaxis.set_major_locator(plt.MaxNLocator(2))
ax_w3.tick_params(axis='both', which='major', labelsize=10, pad = 0.5)
ax_w3.set_yticks(range(-60,61,20))
ax_w3.set_yticklabels(['60$\u00b0$S','40$\u00b0$S','20$\u00b0$S','0$\u00b0$','20$\u00b0$N','40$\u00b0$N','60$\u00b0$N'],fontname = 'Arial',fontsize = 12)
ax_w3.set_ylim(-80,80)
ax_w3.set_xlabel('$\u00b0$C km$^{-1}$',fontname = 'Arial',fontsize = 12)
ax_w3.xaxis.set_label_coords(0.5, -0.09)
ax_w3.set_ylabel('Latitude',fontname = 'Arial',fontsize = 12,fontweight = "bold")
ax_w3.set_xticks([0, 0.05, 0.1, 0.15])
ax_w3.set_xticklabels([0, 0.05, 0.1, 0.15],fontname = 'Arial',fontsize = 12)
formatter = ticker.ScalarFormatter(useMathText=True)
formatter.set_scientific(False) 
formatter.set_powerlimits((-1,1)) 
ax_w3.xaxis.set_major_formatter(formatter) 
ax_w3.text(-0.075,90,'e',fontsize=15, fontweight = "bold",fontname = 'Arial')

#################################################################################################################################################
#################################################################################################################################################
#################################################################################################################################################
fig.delaxes(axs[3])
plt.savefig('../JPEG/Fig6_key_frontal_areas.jpeg',dpi=600,bbox_inches='tight')
plt.show()
/Users/kyang7/anaconda3/lib/python3.11/site-packages/cartopy/mpl/gridliner.py:451: UserWarning: The .xlabels_top attribute is deprecated. Please use .top_labels to toggle visibility instead.
  warnings.warn('The .xlabels_top attribute is deprecated. Please '
/Users/kyang7/anaconda3/lib/python3.11/site-packages/cartopy/mpl/gridliner.py:487: UserWarning: The .ylabels_right attribute is deprecated. Please use .right_labels to toggle visibility instead.
  warnings.warn('The .ylabels_right attribute is deprecated. Please '
/Users/kyang7/anaconda3/lib/python3.11/site-packages/cartopy/mpl/gridliner.py:451: UserWarning: The .xlabels_top attribute is deprecated. Please use .top_labels to toggle visibility instead.
  warnings.warn('The .xlabels_top attribute is deprecated. Please '
/Users/kyang7/anaconda3/lib/python3.11/site-packages/cartopy/mpl/gridliner.py:487: UserWarning: The .ylabels_right attribute is deprecated. Please use .right_labels to toggle visibility instead.
  warnings.warn('The .ylabels_right attribute is deprecated. Please '
/Users/kyang7/anaconda3/lib/python3.11/site-packages/cartopy/mpl/gridliner.py:451: UserWarning: The .xlabels_top attribute is deprecated. Please use .top_labels to toggle visibility instead.
  warnings.warn('The .xlabels_top attribute is deprecated. Please '
/Users/kyang7/anaconda3/lib/python3.11/site-packages/cartopy/mpl/gridliner.py:487: UserWarning: The .ylabels_right attribute is deprecated. Please use .right_labels to toggle visibility instead.
  warnings.warn('The .ylabels_right attribute is deprecated. Please '
<Figure size 18000x9000 with 0 Axes>

Figure 6. MODIS-based frontal activity distribution: density, frequency, and strength. Panels a, c, e: Zonal mean frontal density in %, frequency in %, and strength in °C km-1 based on MODIS SST (in orange). Panels b, d, f: Global means of frontal density, frequency, and strength, with the 80th percentile contours indicated by solid black contours. The latitudinal limits of the MODIS-based analysis are indicated by the black dash lines at 60°N and 60°S.

:)

In [ ]: