Definition of Intensifying & Declining Frontal areas¶

Author: Kai Yang

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

Creation date: 2024-May-19

Latest update: 2025-Jun-03

This Jupyter notebook produces Fig. 7 of the manuscript.

In [2]:
# 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 pylab as plt
import numpy as np
# Inline plotting
%matplotlib inline

from matplotlib import ticker
/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 [3]:
from utils import area,ccrs_land,add_patches
In [7]:
# read trend of frontal metrics

# MODIS
data_set = xr.open_dataset('../datasets/maps/trends_Fdens_Fstre_Ffreq_CHL.nc',chunks={'lat':10,'lon':10})
Fdens = data_set.Fdens_trend
Ffreq = data_set.Ffreq_trend
Fstre = data_set.Fstre_trend

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
Fdens_NANtoZero = Fdens_xr.fillna(0)
Ffreq_NANtoZero = Ffreq_xr.fillna(0)
Fstre_NANtoZero = Fstre_xr.fillna(0)
In [8]:
# read contour shapefiles
Fdens_peak = gpd.read_file(r'../datasets/shapefiles/Fdens_intensify_p80_polygons.shp')
Fdens_trough = gpd.read_file(r'../datasets/shapefiles/Fdens_decline_p80_polygons.shp')
Ffreq_peak = gpd.read_file(r'../datasets/shapefiles/Ffreq_intensify_p80_polygons.shp')
Ffreq_trough = gpd.read_file(r'../datasets/shapefiles/Ffreq_decline_p80_polygons.shp')
Fstre_peak = gpd.read_file(r'../datasets/shapefiles/Fstre_intensify_p80_polygons.shp')
Fstre_trough = gpd.read_file(r'../datasets/shapefiles/Fstre_decline_p80_polygons.shp')
In [9]:
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
axs[0] = fig.add_subplot(4, 1, 1, projection = ccrs.Robinson(central_longitude=180))

# mapping
im1 = Fdens_NANtoZero.plot(ax=axs[0], transform = ccrs.PlateCarree(), add_colorbar=False, 
                 cmap = 'RdBu_r', rasterized=True, vmin = -6, vmax = 6) 

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_peak.plot(transform=ccrs.PlateCarree(),edgecolor='#EC3232', facecolor="None", linewidth=0.8, linestyle = "-", alpha=1, ax = axs[0])
Fdens_trough.plot(transform=ccrs.PlateCarree(),edgecolor='#0787C3', facecolor="None", linewidth=0.8, linestyle = "-", alpha=1, ax = axs[0])
# Fdens_trough_extra.plot(transform=ccrs.PlateCarree(),edgecolor='#0787C3', 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 trend",fontname = 'Arial', fontsize=15, fontweight = "bold",loc = 'left')
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 trend\n (% decade $^{-1}$)', rotation=90, fontname = 'Arial', fontsize=12)
cbar.ax.tick_params(labelsize=11)
for l in cbar.ax.yaxis.get_ticklabels():
    l.set_family("Arial")
cbar.ax.plot([0, 1], [0.9399, 0.9399], '#EC3232')
cbar.ax.plot([0, 1], [-0.7799, -0.7799], '#0787C3')
#################################################################################################################################################
#################################################################################################################################################
#################################################################################################################################################
# Panel d
axs[1] = fig.add_subplot(4, 1, 2, projection = ccrs.Robinson(central_longitude=180))

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

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
Ffreq_peak.plot(transform=ccrs.PlateCarree(),edgecolor='#EC3232', facecolor="None", linewidth=0.8, linestyle = "-", alpha=1, ax = axs[1])
Ffreq_trough.plot(transform=ccrs.PlateCarree(),edgecolor='#0787C3', facecolor="None", linewidth=0.8, linestyle = "-", alpha=1, ax = axs[1])
# Ffreq_trough_extra.plot(transform=ccrs.PlateCarree(),edgecolor='#0787C3', facecolor="None", linewidth=1, linestyle = "--", alpha=1, ax = axs[1])

# 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 trend",fontname = 'Arial', fontsize=15, fontweight = "bold",loc = 'left')
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.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 trend\n (% decade $^{-1}$)', rotation=90, fontname = 'Arial', fontsize=12)
cbar.ax.tick_params(labelsize=11)
for l in cbar.ax.yaxis.get_ticklabels():
    l.set_family("Arial")
cbar.ax.plot([0, 1], [0.8681, 0.8681], '#EC3232')
cbar.ax.plot([0, 1], [-0.7194, -0.7194], '#0787C3')
#################################################################################################################################################
#################################################################################################################################################
#################################################################################################################################################
# Panel f
axs[2] = fig.add_subplot(4, 1, 3, projection = ccrs.Robinson(central_longitude=180))

# mapping
im1 = Fstre_NANtoZero.plot(ax=axs[2], transform = ccrs.PlateCarree(), add_colorbar=False,
                   cmap = 'RdBu_r', 
                   rasterized=True,vmin = -0.01, vmax = 0.01) 

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
Fstre_peak.plot(transform=ccrs.PlateCarree(),edgecolor='#EC3232', facecolor="None", linewidth=0.8, linestyle = "-", alpha=1, ax = axs[2])
Fstre_trough.plot(transform=ccrs.PlateCarree(),edgecolor='#0787C3', facecolor="None", linewidth=0.8, linestyle = "-", alpha=1, ax = axs[2])
# Fstre_trough_extra.plot(transform=ccrs.PlateCarree(),edgecolor='#0787C3', facecolor="None", linewidth=1, linestyle = "--", alpha=1, ax = axs[2])

# 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 trend",fontname = 'Arial', fontsize=15, fontweight = "bold",loc = 'left')
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 trend\n ($\u00b0$C km$^{-1}$ decade $^{-1}$)', rotation=90, fontname = 'Arial', fontsize=12)
cbar.ax.tick_params(labelsize=11)
for l in cbar.ax.yaxis.get_ticklabels():
    l.set_family("Arial")
cbar.ax.plot([0, 1], [0.0018, 0.0018], '#EC3232')
cbar.ax.plot([0, 1], [-0.0017, -0.0017], '#0787C3')

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_NANtoZero.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='#EC3232',linewidth = 0.1)
neg=np.ma.masked_where(zonal_mean_fdens>0, zonal_mean_fdens)
ax_w1.fill_betweenx(y, neg, neg*0, color='#0787C3',linewidth = 0.1)

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

# plot settings
ax_w1.set_ylim(-80, 80)
ax_w1.set_xlim(-1,1)
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_xticks([-1,-0.5,0,0.5,1])
ax_w1.set_xticklabels([-1.0,-0.5,0.0,0.5,1.0],fontname = 'Arial',fontsize = 12)
ax_w1.set_xlabel('% decade$^{-1}$', fontname = 'Arial',fontsize = 12)
ax_w1.xaxis.set_label_coords(0.5, -0.09)
ax_w1.text(-1.6,85,'a',fontname = 'Arial', fontsize=15, fontweight = "bold")
ax_w1.set_ylabel('Latitude',fontname = 'Arial',fontsize = 12,fontweight = "bold")
#################################################################################################################################################
#################################################################################################################################################
#################################################################################################################################################
# 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_NANtoZero.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='#EC3232',linewidth = 0.1)
neg=np.ma.masked_where(zonal_mean_ffreq>0, zonal_mean_ffreq)
ax_w2.fill_betweenx(y, neg, neg*0, color='#0787C3',linewidth = 0.1)

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

# plot settings
ax_w2.set_ylim(-80, 80)
ax_w2.set_xlim(-1,1)
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_xticks([-1,-0.5,0,0.5,1])
ax_w2.set_xticklabels([-1.0,-0.5,0.0,0.5,1.0],fontname = 'Arial',fontsize = 12)
ax_w2.set_xlabel('% decade$^{-1}$', fontname = 'Arial',fontsize = 12)
ax_w2.xaxis.set_label_coords(0.5, -0.09)
ax_w2.text(-1.6,85,'c',fontname = 'Arial', fontsize=15, fontweight = "bold")
ax_w2.set_ylabel('Latitude',fontname = 'Arial',fontsize = 12,fontweight = "bold")
#################################################################################################################################################
#################################################################################################################################################
#################################################################################################################################################
# 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_NANtoZero.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='#EC3232',linewidth = 0.1)
neg=np.ma.masked_where(zonal_mean_fstre>0, zonal_mean_fstre)
ax_w3.fill_betweenx(y, neg, neg*0, color='#0787C3',linewidth = 0.1)

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


# plot settings
ax_w3.set_ylim(-80, 80)
ax_w3.set_xlim(-0.001,0.001)
ax_w3.xaxis.set_label_coords(0.5, -0.12)
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_xticks([-0.001,0,0.001])
ax_w3.set_xticklabels([-0.001,0.00,0.001],fontname = 'Arial',fontsize = 12)
ax_w3.set_xlabel('$\u00b0$C km$^{-1}$ decade$^{-1}$', fontname = 'Arial',fontsize = 12)
ax_w3.xaxis.set_label_coords(0.5, -0.09)
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.0015,85,'e',fontname = 'Arial', fontsize=15, fontweight = "bold")
ax_w3.set_ylabel('Latitude',fontname = 'Arial',fontsize = 12,fontweight = "bold")
#################################################################################################################################################
#################################################################################################################################################
#################################################################################################################################################
fig.delaxes(axs[3])
plt.savefig('../JPEG/Fig7_intensifying_declining_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 7. MODIS-based linear trends of global frontal activity (in density, frequency, and strength). Panels a, c, e: Zonal decadal trends of frontal density in %, frontal frequency in %, and frontal strength °C km-1 based on MODIS SST (red: increasing trend; blue: decreasing trend). Panels b, d, and f: Decadal trends of global density, frequency, and strength of ocean fronts with the 80th percentile contours of increasing trends (red solid line) and decreasing trends (blue solid line).

:)

In [ ]: