Sea ice analysis

Work in Progress

This notebook is currently under development. Content and results may change!

[1]:
%load_ext autoreload
%autoreload
[2]:
%matplotlib inline
import warnings, yaml
warnings.filterwarnings("ignore")
from mom6_tools.MOM6grid import MOM6grid
from mom6_tools.m6toolbox import cime_xmlquery
from ncar_jobqueue import NCARCluster
from dask.distributed import Client
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature
import numpy as np
import xarray as xr
from mom6_tools.m6plot import polarplot
Basemap module not found. Some regional plots may not function properly
ERROR 1: PROJ: proj_create_from_database: Open of /glade/work/gmarques/conda-envs/mom6-tools/share/proj failed
[3]:
# Read in the yaml file
diag_config_yml_path = "diag_config.yml"
diag_config_yml = yaml.load(open(diag_config_yml_path,'r'), Loader=yaml.Loader)
[4]:
caseroot = diag_config_yml['Case']['CASEROOT']
casename = cime_xmlquery(caseroot, 'CASE')
DOUT_S = cime_xmlquery(caseroot, 'DOUT_S')
rundir = cime_xmlquery(caseroot, 'RUNDIR')

if DOUT_S:
  OUTDIR = cime_xmlquery(caseroot, 'DOUT_S_ROOT')+'/ocn/hist/'
  OUTDIR_ice = cime_xmlquery(caseroot, 'DOUT_S_ROOT')+'/ice/hist/'
else:
  OUTDIR = cime_xmlquery(caseroot, 'RUNDIR')
  OUTDIR_ice = OUTDIR

print('Rundir directory is:', rundir)
print('Ice history files are at:', OUTDIR_ice)
print('Casename is:', casename)
Rundir directory is: /glade/derecho/scratch/gmarques/g.e30_a03c.GJRAv4.TL319_t232_wgx3_hycom1_N75.2024.079/run
Ice history files are at: /glade/derecho/scratch/gmarques/archive/g.e30_a03c.GJRAv4.TL319_t232_wgx3_hycom1_N75.2024.079/ice/hist/
Casename is: g.e30_a03c.GJRAv4.TL319_t232_wgx3_hycom1_N75.2024.079
[5]:
# create an empty class object
class args:
  pass# create an empty class object

# load avg dates
avg = diag_config_yml['Avg']

args.start_date = avg['start_date']
args.end_date = avg['end_date']
args.casename = casename
args.ice = casename+diag_config_yml['Fnames']['ice']
args.geom =   casename+diag_config_yml['Fnames']['geom']
args.static = casename+diag_config_yml['Fnames']['static']
args.savefigs = False
args.time_series = True
args.nw = 6 # requesting 6 workers
[6]:
variables = ['hi', 'aice']

def preprocess(ds):
    '''Return the dataset with variables'''
    return ds[variables]

%time ds = xr.open_mfdataset(OUTDIR_ice+args.ice, preprocess=preprocess)
CPU times: user 2min 4s, sys: 2min 27s, total: 4min 32s
Wall time: 9min 7s
[7]:
ds
[7]:
<xarray.Dataset> Size: 2GB
Dimensions:  (time: 732, nj: 480, ni: 540)
Coordinates:
  * time     (time) object 6kB 0001-01-16 12:00:00 ... 0061-12-16 12:00:00
    TLON     (nj, ni) float32 1MB dask.array<chunksize=(480, 540), meta=np.ndarray>
    TLAT     (nj, ni) float32 1MB dask.array<chunksize=(480, 540), meta=np.ndarray>
    ULON     (nj, ni) float32 1MB dask.array<chunksize=(480, 540), meta=np.ndarray>
    ULAT     (nj, ni) float32 1MB dask.array<chunksize=(480, 540), meta=np.ndarray>
    NLON     (nj, ni) float32 1MB dask.array<chunksize=(480, 540), meta=np.ndarray>
    NLAT     (nj, ni) float32 1MB dask.array<chunksize=(480, 540), meta=np.ndarray>
    ELON     (nj, ni) float32 1MB dask.array<chunksize=(480, 540), meta=np.ndarray>
    ELAT     (nj, ni) float32 1MB dask.array<chunksize=(480, 540), meta=np.ndarray>
Dimensions without coordinates: nj, ni
Data variables:
    hi       (time, nj, ni) float32 759MB dask.array<chunksize=(1, 480, 540), meta=np.ndarray>
    aice     (time, nj, ni) float32 759MB dask.array<chunksize=(1, 480, 540), meta=np.ndarray>
Attributes:
    title:               g.e30_a03c.GJRAv4.TL319_t232_wgx3_hycom1_N75.2024.079
    contents:            Diagnostic and Prognostic Variables
    source:              CICE Sea Ice Model, unknown_version_name
    comment:             All years have exactly 365 days
    comment2:            File written on model date 00010201
    comment3:            seconds elapsed into model date:      0
    time_period_freq:    month_1
    time_axis_position:  middle
    conventions:         CF-1.0
    history:             This dataset was created on 2024-10-02 at 15:04
    io_flavor:           io_pio2 cdf1
[8]:
print('\n Selecting data between {} and {}...'.format(args.start_date, args.end_date))
%time ds_sel = ds.sel(time=slice(args.start_date, args.end_date))

 Selecting data between 0031-01-01 and 0062-01-01...
CPU times: user 10.4 ms, sys: 0 ns, total: 10.4 ms
Wall time: 44.3 ms
[9]:
print('\n Computing time mean...')
%time ds_sel_mean = ds_sel.mean('time').compute()

 Computing time mean...
CPU times: user 1min 18s, sys: 2min 53s, total: 4min 12s
Wall time: 9min 18s
[10]:
print('Computing monthly climatology...')
%time  ds_monthly = ds_sel.groupby("time.month").mean('time').compute()
Computing monthly climatology...
CPU times: user 1min 29s, sys: 3min 34s, total: 5min 4s
Wall time: 10min 54s
[11]:
# load obs
obs_path = '/glade/work/gmarques/cesm/datasets/Seaice/'
obs_NH = xr.open_dataset(obs_path+'OBS_NSIDC_sat_NH_T2Ms_sic.nc')
obs_SH = xr.open_dataset(obs_path+'OBS_NSIDC_sat_SH_T2Ms_sic.nc')
[12]:
obs_NH_mean = obs_NH.mean('time').compute()
obs_SH_mean = obs_SH.mean('time').compute()
[13]:
obs_NH_monthly = obs_NH.groupby("time.month").mean('time').compute()
obs_SH_monthly = obs_SH.groupby("time.month").mean('time').compute()

Sea ice thickness

Annual mean

[14]:
# Sea ice thickness
aice_mean = np.ma.masked_invalid(ds_monthly['aice'].mean('month').values) * 100.
hi_mean = np.ma.masked_invalid(ds_monthly['hi'].mean('month').values)
hi_mean = np.ma.masked_where(aice_mean < 15.0, hi_mean)
suptitle = ('ANN mean sea ice thickness, ' + str(args.start_date) + ' to ' + str(args.end_date))
%matplotlib inline
# SH
fig = plt.figure(figsize=(10,8))
ax = plt.gca(projection=ccrs.SouthPolarStereo())
polarplot(hi_mean, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,2), axis=ax)
plt.suptitle(suptitle)

# NH
fig = plt.figure(figsize=(10,8))
ax = plt.gca(projection=ccrs.NorthPolarStereo())
polarplot(hi_mean, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,4), axis=ax, proj='NP')
plt.suptitle(suptitle)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[14], line 9
      7 # SH
      8 fig = plt.figure(figsize=(10,8))
----> 9 ax = plt.gca(projection=ccrs.SouthPolarStereo())
     10 polarplot(hi_mean, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,2), axis=ax)
     11 plt.suptitle(suptitle)

TypeError: gca() got an unexpected keyword argument 'projection'
<Figure size 1000x800 with 0 Axes>

JFM

[ ]:
aice_JFM = np.ma.masked_invalid(ds_monthly['aice'].sel(month=[1,2,3]).mean('month').values) * 100.
hi_JFM = np.ma.masked_invalid(ds_monthly['hi'].sel(month=[1,2,3]).mean('month').values)
hi_JFM = np.ma.masked_where(aice_JFM < 15.0, hi_JFM)
suptitle = ('JFM mean sea ice thickness, ' + str(args.start_date) + ' to ' + str(args.end_date))
%matplotlib inline
# SH
fig = plt.figure(figsize=(10,8))
ax = plt.gca(projection=ccrs.SouthPolarStereo())
polarplot(hi_JFM, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,2), axis=ax)
plt.suptitle(suptitle)

# NH
fig = plt.figure(figsize=(10,8))
ax = plt.gca(projection=ccrs.NorthPolarStereo())
polarplot(hi_JFM, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,4), axis=ax, proj='NP')
plt.suptitle(suptitle)

AMJ

[ ]:
aice_AMJ = np.ma.masked_invalid(ds_monthly['aice'].sel(month=[4,5,6]).mean('month').values) * 100.
hi_AMJ = np.ma.masked_invalid(ds_monthly['hi'].sel(month=[4,5,6]).mean('month').values)
hi_AMJ = np.ma.masked_where(aice_AMJ < 15.0, hi_AMJ)
suptitle = ('AMJ mean sea ice thickness, ' + str(args.start_date) + ' to ' + str(args.end_date))
%matplotlib inline
# SH
fig = plt.figure(figsize=(10,8))
ax = plt.gca(projection=ccrs.SouthPolarStereo())
polarplot(hi_AMJ, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,2), axis=ax)
plt.suptitle(suptitle)

# NH
fig = plt.figure(figsize=(10,8))
ax = plt.gca(projection=ccrs.NorthPolarStereo())
polarplot(hi_AMJ, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,4), axis=ax, proj='NP')
plt.suptitle(suptitle)

JAS

[ ]:
aice_JAS = np.ma.masked_invalid(ds_monthly['aice'].sel(month=[7,8,9]).mean('month').values) * 100.
hi_JAS = np.ma.masked_invalid(ds_monthly['hi'].sel(month=[7,8,9]).mean('month').values)
hi_JAS = np.ma.masked_where(aice_JAS < 15.0, hi_JAS)
suptitle = ('JAS mean sea ice thickness, ' + str(args.start_date) + ' to ' + str(args.end_date))
%matplotlib inline
# SH
fig = plt.figure(figsize=(10,8))
ax = plt.gca(projection=ccrs.SouthPolarStereo())
polarplot(hi_JAS, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,2), axis=ax)
plt.suptitle(suptitle)

# NH
fig = plt.figure(figsize=(10,8))
ax = plt.gca(projection=ccrs.NorthPolarStereo())
polarplot(hi_JAS, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,4), axis=ax, proj='NP')
plt.suptitle(suptitle)

OND

[ ]:
aice_OND = np.ma.masked_invalid(ds_monthly['aice'].sel(month=[10,11,12]).mean('month').values) * 100.
hi_OND = np.ma.masked_invalid(ds_monthly['hi'].sel(month=[10,11,12]).mean('month').values)
hi_OND = np.ma.masked_where(aice_OND < 15.0, hi_OND)
suptitle = ('OND mean sea ice thickness, ' + str(args.start_date) + ' to ' + str(args.end_date))
%matplotlib inline
# SH
fig = plt.figure(figsize=(10,8))
ax = plt.gca(projection=ccrs.SouthPolarStereo())
polarplot(hi_OND, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,2), axis=ax)
plt.suptitle(suptitle)

# NH
fig = plt.figure(figsize=(10,8))
ax = plt.gca(projection=ccrs.NorthPolarStereo())
polarplot(hi_OND, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,4), axis=ax, proj='NP')
plt.suptitle(suptitle)
[ ]:
(obs_SH_mean.sic * 100.).plot()
[ ]:
tmp = obs_SH_mean['sic'].values * 100.
#tmp1 = np.ma.masked_where(tmp < 15.0, tmp)
fig = plt.figure(figsize=(10,8))
ax = plt.gca(projection=ccrs.SouthPolarStereo())
ax.contour(obs_SH_mean.lon.values, obs_SH_mean.lat.values, tmp, levels=[16.5], transform=ccrs.PlateCarree(), colors='black')

Sea ice concentration

[ ]:

aice_mean = np.ma.masked_where(aice_mean <= 15.0, aice_mean) suptitle = ('ANN mean ice concentration, ' + str(args.start_date) + ' to ' + str(args.end_date)) %matplotlib inline # SH fig = plt.figure(figsize=(10,8)) ax = plt.gca(projection=ccrs.SouthPolarStereo()) polarplot(aice_mean, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,100), axis=ax) ax.contour(obs_SH_mean.lon.values, obs_SH_mean.lat.values, tmp, levels=[16.5], transform=ccrs.PlateCarree(), colors='black', linestyles='solid') plt.suptitle(suptitle) # NH fig = plt.figure(figsize=(10,8)) ax = plt.gca(projection=ccrs.NorthPolarStereo()) polarplot(aice_mean, grd, title=dcase.casename, debug=False, colormap=plt.cm.gist_ncar, clim=(0,100), axis=ax, proj='NP') plt.suptitle(suptitle)

Northern Hemisphere

Maximum sea ice thickness

[ ]:
from mom6_tools.latlon_analysis import create_xarray_dataset, plot_area_ave_stats
from mom6_tools.m6plot import myStats
[ ]:
dtime = seaice.time.values
# variable name
var = 'hi'
# create datasets
ds_sh = create_xarray_dataset(var,'m',dtime)
ds_nh = create_xarray_dataset(var,'m',dtime)

# loop in time
for t in range(0,len(dtime)):
    # northern hemisphere
    tmp = np.ma.masked_invalid(seaice[var].sel(time=dtime[t]).values)
    tmp_nh = np.ma.masked_where(grd.geolat < 0, tmp)
    # get stats
    sMin, sMax, mean, std, rms = myStats(tmp_nh, area=None)
    # update Dataset
    ds_nh[var][1,t]  = sMax
    # southern hemisphere
    tmp_sh = np.ma.masked_where(grd.geolat > 0, tmp)
    # get stats
    sMin, sMax, mean, std, rms = myStats(tmp_sh, area=None)
    # update Dataset
    ds_sh[var][1,t] = sMax

Southern Hemisphere

[ ]:
sh = ds_sh.sel(stats='max')
fig = plt.figure(figsize=(12, 6))
ax  = fig.add_subplot(111)
sh.hi.plot(ax=ax)
plt.title('Maximum sea ice thickness, southern hemisphere', fontsize=14)
plt.xlabel('Time [years]')

Northern Hemisphere

[ ]:
nh = ds_nh.sel(stats='max')
fig = plt.figure(figsize=(12, 6))
ax  = fig.add_subplot(111)
nh.hi.plot(ax=ax)
plt.title('Maximum sea ice thickness, northern hemisphere', fontsize=14)
plt.xlabel('Time [years]')

Sea ice extent

[ ]:
dtime = seaice.time.values
# variable name
var = 'aice'
#
area_sh = []
area_nh = []

# loop in time
for t in range(len(dtime)):
    tmp = np.ma.masked_invalid(seaice[var].sel(time=dtime[t]).values)
    # mask southern hemisphere
    tmp_nh = np.ma.masked_where(grd.geolat < 0, grd.area_t)
    # mask northern hemisphere
    tmp_sh = np.ma.masked_where(grd.geolat > 0, grd.area_t)
    # mask if aggregrated concentration <= 0.15
    tmp_nh = np.ma.masked_where(tmp <= 0.15, tmp_nh*tmp)
    tmp_sh = np.ma.masked_where(tmp <= 0.15, tmp_sh*tmp)
    # append data
    area_sh.append(np.sum(tmp_sh)*1.0e-12) # 1.0e6 km^2
    area_nh.append(np.sum(tmp_nh)*1.0e-12) # 1.0e6 km^2

Southern hemisphere

[ ]:
fig = plt.figure(figsize=(12, 6))
plt.plot(dtime,area_sh)
plt.title('Sea ice area, southern hemisphere', fontsize=14)
plt.xlabel('Time [years]', fontsize=14); plt.ylabel('x 1.0e6 km$^2$', fontsize=14)

Northern hemisphere

[ ]:
fig = plt.figure(figsize=(12, 6))
plt.plot(dtime,area_nh)
plt.title('Sea ice area, northern hemisphere', fontsize=14)
plt.xlabel('Time [years]', fontsize=14); plt.ylabel('x 1.0e6 km$^2$', fontsize=14)

Under development

[ ]:
import matplotlib.path as mpath
fig = plt.figure(figsize=[10, 8])
ice = (seaice.aice[-1,:,:].data)
ax1 = plt.subplot(1, 1, 1, projection=ccrs.NorthPolarStereo())
ax1.set_extent([-180, 180, 50, 90], ccrs.PlateCarree())
ax1.add_feature(cartopy.feature.LAND)
ax1.gridlines()
# Compute a circle in axes coordinates, which we can use as a boundary
# for the map. We can pan/zoom as much as we like - the boundary will be
# permanently circular.
theta = np.linspace(0, 2*np.pi, 100)
center, radius = [0.5, 0.5], 0.5
verts = np.vstack([np.sin(theta), np.cos(theta)]).T
circle = mpath.Path(verts * radius + center)
ax1.set_boundary(circle, transform=ax1.transAxes)
#colormap = 'rainbow'
cs = ax1.pcolormesh(grd.geolon,grd.geolat,ice,transform=ccrs.PlateCarree(),cmap='Blues_r', shading='flat')
fig.colorbar(cs)
# Add Land
ax1.add_feature( cartopy.feature.LAND, zorder=1, edgecolor='none', facecolor='#fae5c9') #fae5c9')
# add Ocean
ax1.add_feature(cartopy.feature.OCEAN)
# Add coastline
ax1.coastlines(color='black')
# Add lat lon rings
ax1.gridlines(alpha='0.1',color='black')
im1 = ax1.contour(grd.geolon,grd.geolat,ice,[15],colors='red', transform=ccrs.PlateCarree())
plt.title('Model, Years ' + str(args.year_start) + ' to ' + str(args.year_end))