mom6-tools Documentation
Release 0.0.post86
mom6-tools developers
Nov 12, 2020
User guide
1 Installation (Coming Soon!) 3
1.1 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 API Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
1.3 Installing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
2 Indices and tables 163
i
ii
mom6-tools Documentation, Release 0.0.post86
Tools to support analysis of MOM6-CESM model solutions. See documentation for more information.
User guide 1
mom6-tools Documentation, Release 0.0.post86
2 User guide
CHAPTER 1
Installation (Coming Soon!)
mom6-tools can be installed from PyPI with pip:
pip install mom6-tools
It is also available from conda-forge for conda installations:
conda install -c conda-forge mom6-tools
User guide
• Examples
1.1 Examples
1.1.1 Example on how to configure a case using mom6-tools
This is a very simple example showing how to read diag_config.yaml, create a case instance, compute a clima-
tology and visualize the results.
[1]: from mom6_tools.DiagsCase import DiagsCase
import yaml
import xarray as xr
import matplotlib
from mom6_tools import m6toolbox
%matplotlib inline
[2]: # 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)
[3]: # Create the case instance
dcase = DiagsCase(diag_config_yml['Case'])
3
mom6-tools Documentation, Release 0.0.post86
[4]: dcase.casename
[4]: 'g.c2b6.GJRA.TL319_t061.long_JRA_mct.076'
[5]: # Load the grid
grd = dcase.grid
MOM6 grid successfully loaded...
[6]: parallel, cluster, client = m6toolbox.request_workers(6)
Requesting 6 workers...
/proxy/46593/status
[7]: RUNDIR = dcase.get_value('RUNDIR')
%time ds = xr.open_mfdataset(RUNDIR+'/'+dcase.casename+'.mom6.sfc_*.nc', \
parallel=True, data_vars='minimal', chunks={'time': 12},\
coords='minimal', compat='override')
CPU times: user 4.67 s, sys: 494 ms, total: 5.16 s
Wall time: 1min 37s
[8]: ds
[8]: <xarray.Dataset>
Dimensions: (nv: 2, time: 21170, xh: 540, xq: 540, yh: 458, yq: 458)
Coordinates:
* yh (yh) float64 -79.2 -79.08 -78.95 -78.82 ... 87.64 87.71 87.74
* nv (nv) float64 1.0 2.0
* xh (xh) float64 -286.7 -286.0 -285.3 -284.7 ... 71.33 72.0 72.67
* yq (yq) float64 -79.14 -79.01 -78.89 -78.76 ... 87.68 87.73 87.74
* xq (xq) float64 -286.3 -285.7 -285.0 -284.3 ... 71.67 72.33 73.0
* time (time) object 0001-01-01 12:00:00 ... 0058-12-31 12:00:00
Data variables:
SSH (time, yh, xh) float32 dask.array<chunksize=(12, 458, 540), meta=np.
˓→ndarray>
tos (time, yh, xh) float32 dask.array<chunksize=(12, 458, 540), meta=np.
˓→ndarray>
sos (time, yh, xh) float32 dask.array<chunksize=(12, 458, 540), meta=np.
˓→ndarray>
SSU (time, yh, xq) float32 dask.array<chunksize=(12, 458, 540), meta=np.
˓→ndarray>
SSV (time, yq, xh) float32 dask.array<chunksize=(12, 458, 540), meta=np.
˓→ndarray>
speed (time, yh, xh) float32 dask.array<chunksize=(12, 458, 540), meta=np.
˓→ndarray>
mlotst (time, yh, xh) float32 dask.array<chunksize=(12, 458, 540), meta=np.
˓→ndarray>
oml (time, yh, xh) float32 dask.array<chunksize=(12, 458, 540), meta=np.
˓→ndarray>
average_T1 (time) object dask.array<chunksize=(12,), meta=np.ndarray>
average_T2 (time) object dask.array<chunksize=(12,), meta=np.ndarray>
average_DT (time) timedelta64[ns] dask.array<chunksize=(12,), meta=np.ndarray>
time_bnds (time, nv) timedelta64[ns] dask.array<chunksize=(12, 2), meta=np.
˓→ndarray>
(continues on next page)
4 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
Attributes:
filename: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076.mom6.sfc_0001.nc
title: MOM6 diagnostic fields table for CESM case: g.c2b6.GJR...
associated_files: area_t: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076.mom6.s...
grid_type: regular
grid_tile: N/A
[9]: # Plot 5-yearly average sst
sst = ds['tos'].mean('time').load()
[10]: sst.plot(vmin=-2, vmax=32)
[10]: <matplotlib.collections.QuadMesh at 0x2b1e95f82da0>
[ ]: dd
1.1.2 Masks generation
The porpuses of this notebook is to show how to generate ocean masks for different regions. It uses functions genBas-
inMasks.
[1]: from mom6_tools.m6plot import xyplot
from mom6_tools.m6toolbox import genBasinMasks
from mom6_tools.MOM6grid import MOM6grid
from mom6_tools.DiagsCase import DiagsCase
import yaml
import numpy
import xarray as xr
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
%matplotlib inline
Basemap module not found. Some regional plots may not function properly
1.1. Examples 5
mom6-tools Documentation, Release 0.0.post86
[2]: # 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)
[3]: # Create the case instance
dcase = DiagsCase(diag_config_yml['Case'])
RUNDIR = dcase.get_value('RUNDIR')
print('Run directory is:', RUNDIR)
print('Casename is:', dcase.casename)
Run directory is: /glade/scratch/gmarques/g.c2b6.GJRA.TL319_t061.long_JRA_mct.076/run
Casename is: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076
[4]: stream = True
# Load mom6 grid
grd = dcase.grid
depth = grd.depth_ocean
# remote Nan's, otherwise genBasinMasks won't work
depth[numpy.isnan(depth)] = 0.0
MOM6 grid successfully loaded...
Create masks for different regions
[5]: basin_code = genBasinMasks(grd.geolon, grd.geolat, depth)
11.16427964664149 64.78854837178643 [391, 434]
Check code number for each region defined
[6]: vals = numpy.unique(basin_code)
[7]: for v in vals:
dummy = numpy.zeros(basin_code.shape)
dummy[basin_code == v] = v
dummy = numpy.ma.masked_where(depth == 0., dummy)
plt.figure(figsize=(12,8))
xyplot(dummy, grd.geolon, grd.geolat,title='Code = '+str(v))
<Figure size 864x576 with 0 Axes>
6 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
<Figure size 864x576 with 0 Axes>
<Figure size 864x576 with 0 Axes>
1.1. Examples 7
mom6-tools Documentation, Release 0.0.post86
<Figure size 864x576 with 0 Axes>
<Figure size 864x576 with 0 Axes>
8 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
<Figure size 864x576 with 0 Axes>
<Figure size 864x576 with 0 Axes>
1.1. Examples 9
mom6-tools Documentation, Release 0.0.post86
<Figure size 864x576 with 0 Axes>
<Figure size 864x576 with 0 Axes>
10 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
<Figure size 864x576 with 0 Axes>
<Figure size 864x576 with 0 Axes>
1.1. Examples 11
mom6-tools Documentation, Release 0.0.post86
<Figure size 864x576 with 0 Axes>
<Figure size 864x576 with 0 Axes>
12 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[8]: # reload codes as dataarray
basin_code = genBasinMasks(grd.geolon, grd.geolat, depth, xda=True)
11.16427964664149 64.78854837178643 [391, 434]
Noticed that point [391, 434] does not belong to any of the masks generated. This is okay but let see where this point
is located:
[9]: plt.figure(figsize=(12,8))
xyplot(basin_code[0,:].values, grd.geolon, grd.geolat)
plt.plot(grd.geolon[434,391], grd.geolat[434,391],'xr', ms=10);
<Figure size 864x576 with 0 Axes>
1.1. Examples 13
mom6-tools Documentation, Release 0.0.post86
Now, let’s plot the masking for all the regions:
[10]: for r in range(len(basin_code.region)):
#plt.figure(figsize=(12,8))
xyplot((basin_code[0,:]+basin_code[r,:]*2).values, grd.geolon, grd.geolat,
title=str(basin_code['region'][r].values))
14 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 15
mom6-tools Documentation, Release 0.0.post86
16 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 17
mom6-tools Documentation, Release 0.0.post86
18 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 19
mom6-tools Documentation, Release 0.0.post86
20 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1.3 Ocean stats
[1]: from mom6_tools.DiagsCase import DiagsCase
import yaml,os
import pandas as pd
(continues on next page)
1.1. Examples 21
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
import glob
import xarray
import cftime
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams.update({'font.size': 22})
[2]: # Read in the yaml file
diag_config_yml_path = "/glade/u/home/gmarques/libs/mom6-tools/docs/source/examples/
˓→diag_config.yml"
diag_config_yml = yaml.load(open(diag_config_yml_path,'r'), Loader=yaml.Loader)
[3]: # Create the case instance
dcase = DiagsCase(diag_config_yml['Case'])
print('Casename is:', dcase.casename)
RUNDIR = dcase.get_value('RUNDIR')
all_files = glob.glob(os.path.join(RUNDIR, "ocean.stats"))
Casename is: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076
[4]: colnames = ['Step','Day','Truncs','Energy/Mass','Maximum CFL', 'Mean Sea Level',
˓→'Total Mass', 'Mean Salin', 'Mean Temp', 'Frac Mass Err', 'Salin Err', 'Temp Err']
units = ['nondim','days','nondim','m2 s-2','nondim', 'm', 'kg', 'PSU', 'degC', 'nondim
˓→', 'PSU', 'degC']
[5]: df = pd.read_csv(all_files[0], header=1, error_bad_lines=False, sep=',', names =
˓→colnames)
[6]: df.head(10)
[6]: Step Day Truncs Energy/Mass Maximum CFL \
0 0 0.0 0 En 2.4571649248052563E-23 CFL 0.00000
1 23 1.0 0 En 9.8082713560573701E-04 CFL 0.05888
2 47 2.0 0 En 1.0477053248426859E-03 CFL 0.05146
3 71 3.0 0 En 1.1103548714490880E-03 CFL 0.05868
4 95 4.0 0 En 1.0897107455835520E-03 CFL 0.06285
5 119 5.0 0 En 1.0783292792344746E-03 CFL 0.07048
6 143 6.0 0 En 1.0541041612146653E-03 CFL 0.06984
7 167 7.0 0 En 1.0405843511657768E-03 CFL 0.09139
8 191 8.0 0 En 1.0315200927403297E-03 CFL 0.07750
9 215 9.0 0 En 1.0428894544672127E-03 CFL 0.08749
Mean Sea Level Total Mass Mean Salin Mean Temp Frac Mass Err \
0 SL -1.3599E-10 M 1.38614E+21 S 34.7202 T 3.5781 Me 0.00E+00
1 SL -1.3812E-10 M 1.38614E+21 S 34.7202 T 3.5780 Me 1.78E-19
2 SL -1.3812E-10 M 1.38614E+21 S 34.7202 T 3.5780 Me 1.73E-20
3 SL -1.3883E-10 M 1.38614E+21 S 34.7202 T 3.5779 Me -1.34E-19
4 SL -1.3599E-10 M 1.38614E+21 S 34.7202 T 3.5779 Me -4.33E-19
5 SL -1.3812E-10 M 1.38614E+21 S 34.7202 T 3.5778 Me 3.42E-19
6 SL -1.3670E-10 M 1.38614E+21 S 34.7202 T 3.5778 Me 1.21E-19
7 SL -1.3670E-10 M 1.38614E+21 S 34.7202 T 3.5779 Me 2.71E-19
8 SL -1.3812E-10 M 1.38614E+21 S 34.7202 T 3.5779 Me 4.49E-19
9 SL -1.4097E-10 M 1.38614E+21 S 34.7202 T 3.5780 Me -2.09E-19
Salin Err Temp Err
(continues on next page)
22 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
0 Se 0.00E+00 Te 0.00E+00
1 Se 1.66E-16 Te -1.62E-18
2 Se -1.73E-17 Te -6.76E-18
3 Se -1.62E-17 Te 3.13E-18
4 Se -7.36E-18 Te -2.23E-18
5 Se 5.70E-17 Te 3.63E-18
6 Se -1.85E-17 Te -9.41E-19
7 Se 1.30E-17 Te 5.78E-19
8 Se -2.64E-17 Te 1.02E-18
9 Se 2.38E-17 Te 1.99E-18
[7]: # transfor to xarray and change/rename the coords
xr = df.to_xarray()
del xr['index'], xr['Step']
xr = xr.rename({'index': 'Day'})
xr.set_coords('Day')
[7]: <xarray.Dataset>
Dimensions: (Day: 21176)
Coordinates:
* Day (Day) float64 0.0 1.0 2.0 ... 2.117e+04 2.117e+04 2.117e+04
Data variables:
Truncs (Day) int64 0 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0 0
Energy/Mass (Day) object ' En 2.4571649248052563E-23' ... ' En 1.
˓→0158479597159721E-03'
Maximum CFL (Day) object ' CFL 0.00000' ... ' CFL 0.08558'
Mean Sea Level (Day) object ' SL -1.3599E-10' ... ' SL -1.3243E-10'
Total Mass (Day) object ' M 1.38614E+21' ... ' M 1.38614E+21'
Mean Salin (Day) object ' S 34.7202' ' S 34.7202' ... ' S 34.7203'
Mean Temp (Day) object ' T 3.5781' ' T 3.5780' ... ' T 3.6890'
Frac Mass Err (Day) object ' Me 0.00E+00' ... ' Me 8.69E-20'
Salin Err (Day) object ' Se 0.00E+00' ... ' Se -4.23E-17'
Temp Err (Day) object ' Te 0.00E+00' ... ' Te -7.12E-21'
[8]: # add attrs units
k = 1
for var in xr.variables:
print(var,k, units[k])
xr[var].attrs['units'] = units[k]
k = k + 1
Day 1 days
Truncs 2 nondim
Energy/Mass 3 m2 s-2
Maximum CFL 4 nondim
Mean Sea Level 5 m
Total Mass 6 kg
Mean Salin 7 PSU
Mean Temp 8 degC
Frac Mass Err 9 nondim
Salin Err 10 PSU
Temp Err 11 degC
1.1. Examples 23
mom6-tools Documentation, Release 0.0.post86
Some columns have strings in them (e.g., CFL and En) and we need to remove them.
[9]: colnames = ['Energy/Mass','Maximum CFL', 'Mean Sea Level', 'Total Mass', 'Mean Salin',
˓→ 'Mean Temp', 'Frac Mass Err', 'Salin Err', 'Temp Err']
for var in colnames:
print(var)
nt = len(xr[var])
dummy = np.zeros(nt)
for t in range(nt):
dummy[t] = float(str(xr[var][t].values).strip().split()[1])
xr[var].values[:] = dummy[:]
Energy/Mass
Maximum CFL
Mean Sea Level
Total Mass
Mean Salin
Mean Temp
Frac Mass Err
Salin Err
Temp Err
[10]: xr = xr.astype(float)
xr.set_coords('Day')
#xr['Day'] = xr['Day']/365.
for var in colnames:
plt.figure(figsize=(12,8))
xr[var].plot()
24 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 25
mom6-tools Documentation, Release 0.0.post86
26 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 27
mom6-tools Documentation, Release 0.0.post86
28 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[11]: df_stats = xarray.open_dataset(RUNDIR+'/ocean.stats.nc')
df_stats
[11]: <xarray.Dataset>
Dimensions: (Interface: 66, Layer: 65, Time: 21176)
Coordinates:
* Layer (Layer) float64 1.25 3.75 6.25 ... 5.627e+03 5.876e+03
* Interface (Interface) float64 0.0 2.5 5.0 ... 5.503e+03 5.751e+03 6e+03
* Time (Time) timedelta64[ns] 0 days 1 days ... 21170 days
Data variables:
Ntrunc (Time) float64 ...
En (Time) float64 ...
APE (Time, Interface) float64 ...
KE (Time, Layer) float64 ...
H0 (Time, Interface) float64 ...
Mass_lay (Time, Layer) float64 ...
Mass (Time) float64 ...
Mass_chg (Time) float64 ...
Mass_anom (Time) float64 ...
max_CFL_trans (Time) float64 ...
max_CFL_lin (Time) float64 ...
Salt (Time) float64 ...
Salt_chg (Time) float64 ...
Salt_anom (Time) float64 ...
Heat (Time) float64 ...
Heat_chg (Time) float64 ...
Heat_anom (Time) float64 ...
age (Time) float64 ...
(continues on next page)
1.1. Examples 29
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
Attributes:
filename: ./ocean.stats.nc
[12]: for var in df_stats.variables:
#print(var)
if var not in ['KE','APE','H0','Mass_lay','Layer', 'Interface','Time']:
plt.figure(figsize=(10,8))
df_stats[var].plot()
30 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 31
mom6-tools Documentation, Release 0.0.post86
32 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 33
mom6-tools Documentation, Release 0.0.post86
34 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 35
mom6-tools Documentation, Release 0.0.post86
36 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 37
mom6-tools Documentation, Release 0.0.post86
38 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 39
mom6-tools Documentation, Release 0.0.post86
40 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 41
mom6-tools Documentation, Release 0.0.post86
42 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[ ]:
1.1.4 Analysis of Surface Fields
mom6_tools.MOM6grid returns an object with MOM6 grid data.
mom6_tools.latlon_analysis has a collection of tools used to perform spatial analysis (e.g., time averages
and spatial mean).
The goal of this notebook is the following:
1) server as an example of how to post-process CESM/MOM6 output;
2) create time averages of surface fields;
3) create time-series of globally-averaged surface fields;
4) compare model results vs. observations (TODO);
5) compare model results vs. another model results (TODO).
1.1. Examples 43
mom6-tools Documentation, Release 0.0.post86
[1]: %matplotlib inline
from mom6_tools.MOM6grid import MOM6grid
from mom6_tools.DiagsCase import DiagsCase
from mom6_tools.latlon_analysis import time_mean_latlon
import matplotlib.pyplot as plt
import warnings, yaml
warnings.filterwarnings("ignore")
Basemap module not found. Some regional plots may not function properly
[2]: # Read in the yaml file
diag_config_yml_path = "/glade/u/home/gmarques/libs/mom6-tools/docs/source/examples/
˓→diag_config.yml"
diag_config_yml = yaml.load(open(diag_config_yml_path,'r'), Loader=yaml.Loader)
[3]: # Create the case instance
dcase = DiagsCase(diag_config_yml['Case'])
RUNDIR = dcase.get_value('RUNDIR')
print('Run directory is:', RUNDIR)
print('Casename is:', dcase.casename)
Run directory is: /glade/scratch/gmarques/g.c2b6.GJRA.TL319_t061.long_JRA_mct.076/run
Casename is: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076
[4]: # The following parameters must be set accordingly
######################################################
# Path to the run directory
path = "/glade/scratch/gmarques/"+dcase.casename+"/run/"
# name of ocean static file
static = dcase.casename+'.mom6.static.nc'
# name of forcing file
surface = dcase.casename+'.mom6.sfc_00*.nc'
# initial and final years for computing time mean
year_start = 1
year_end = 85
# array with 2D forcing variables to be processed
variables = ['SST','SSS','SSH']
# Put your name and email address below
author = 'Gustavo Marques (
[email protected])'
######################################################
# create an empty class object
class args:
pass
args.infile = path+surface
# set avg dates
avg = diag_config_yml['Avg']
args.start_date = avg['start_date']
args.end_date = avg['end_date']
args.case_name = dcase.casename
args.variables = variables
args.savefigs = False
args.time_series = True
args.nw = 6 # requesting 6 workers
[5]: # load mom6 grid
grd = MOM6grid(path+static)
(continues on next page)
44 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
# plot time averages. If variables is NOT specified, all 2D variables will be plotted.
#time_mean_latlon_plot(args,grd, variables=args.variables)
time_mean_latlon(args,grd)
MOM6 grid successfully loaded...
Requesting 6 workers...
/proxy/38817/status
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
<ipython-input-5-f6d6526d1eb0> in <module>
3 # plot time averages. If variables is NOT specified, all 2D variables will be
˓→plotted.
4 #time_mean_latlon_plot(args,grd, variables=args.variables)
----> 5 time_mean_latlon(args,grd)
~/libs/mom6-tools/mom6_tools/latlon_analysis.py in time_mean_latlon(args, grd,
˓→variables)
174 dtime = ds.time.values
175 data = np.ma.masked_invalid(ds1[var].values)
--> 176 ds_new = create_xarray_dataset(var,units,dtime)
177 # loop in time
178 for t in range(0,len(dtime)):
UnboundLocalError: local variable 'units' referenced before assignment
[ ]:
1.1.5 Analysis of Forcing Fields
mom6_tools.MOM6grid returns an object with MOM6 grid data.
mom6_tools.latlon_analysis has a collection of tools used to perform spatial analysis (e.g., time averages
and spatial mean).
The goal of this notebook is the following:
1) serve as an example of how to post-process CESM/MOM6 output;
2) create time averages of forcing fields;
3) create time-series of globally-averaged forcing fields;
4) compare model results vs. observations (TODO);
5) compare model results vs. another model results (TODO).
[1]: %matplotlib inline
from mom6_tools.MOM6grid import MOM6grid
from mom6_tools.DiagsCase import DiagsCase
from mom6_tools.m6toolbox import genBasinMasks
from mom6_tools.latlon_analysis import time_mean_latlon
import matplotlib.pyplot as plt
import numpy as np
import yaml
1.1. Examples 45
mom6-tools Documentation, Release 0.0.post86
Basemap module not found. Some regional plots may not function properly
[2]: # Read in the yaml file
diag_config_yml_path = "/glade/u/home/gmarques/libs/mom6-tools/docs/source/examples/
˓→diag_config.yml"
diag_config_yml = yaml.load(open(diag_config_yml_path,'r'), Loader=yaml.Loader)
[3]: # Create the case instance
dcase = DiagsCase(diag_config_yml['Case'])
RUNDIR = dcase.get_value('RUNDIR')
print('Run directory is:', RUNDIR)
print('Casename is:', dcase.casename)
Run directory is: /glade/scratch/gmarques/g.c2b6.GJRA.TL319_t061.long_JRA_mct.076/run
Casename is: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076
[4]: # create an empty class object
class args:
pass
args.case_name = dcase.casename
args.start_date = ''
args.end_date = ''
args.savefigs = False
[5]: # set avg dates
avg = diag_config_yml['Avg']
if not args.start_date : args.start_date = avg['start_date']
if not args.end_date : args.end_date = avg['end_date']
[9]: # The following parameters must be set accordingly
######################################################
# name of forcing file
forcing = dcase.casename+'.mom6.hm*.nc'
######################################################
args.infile = RUNDIR+'/'+forcing
# array with 2D forcing variables to be processed
args.variables = ['hfds','PRCmE','taux','tauy']
args.savefigs = False
args.time_series = True
args.nw = 6 # number of workers
[10]: # Load the grid
grd = dcase.grid
depth = grd.depth_ocean
# remove Nan's, otherwise genBasinMasks won't work
depth[np.isnan(depth)] = 0.0
basin_code = genBasinMasks(grd.geolon, grd.geolat, depth, verbose=False)
11.16427964664149 64.78854837178643 [391, 434]
[11]: %matplotlib inline
# plot time averages. If variables is NOT specified, all 2D variables will be plotted.
(continues on next page)
46 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
#time_mean_latlon_plot(args,grd, variables=args.variables)
time_mean_latlon(args,grd,args.variables)
Requesting 6 workers...
/proxy/45255/status
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-11-41e50666a1cc> in <module>
2 # plot time averages. If variables is NOT specified, all 2D variables will be
˓→plotted.
3 #time_mean_latlon_plot(args,grd, variables=args.variables)
----> 4 time_mean_latlon(args,grd,args.variables)
~/libs/mom6-tools/mom6_tools/latlon_analysis.py in time_mean_latlon(args, grd,
˓→variables)
134 ds = xr.open_mfdataset(args.infile, \
135 parallel=True, data_vars='minimal', chunks={'time': 12},\
--> 136 coords='minimal', compat='override', preprocess=preprocess)
137 else:
138 ds = xr.open_mfdataset(args.infile, \
~/miniconda3/envs/analysis/lib/python3.7/site-packages/xarray/backends/api.py in open_
˓→mfdataset(paths, chunks, concat_dim, compat, preprocess, engine, lock, data_vars,
˓→coords, combine, autoclose, parallel, join, **kwargs)
931 coords=coords,
932 join=join,
--> 933 from_openmfds=True,
934 )
935 elif combine == "nested":
~/miniconda3/envs/analysis/lib/python3.7/site-packages/xarray/core/combine.py in auto_
˓→combine(datasets, concat_dim, compat, data_vars, coords, fill_value, join, from_
˓→openmfds)
853 coords=coords,
854 fill_value=fill_value,
--> 855 join=join,
856 )
857
~/miniconda3/envs/analysis/lib/python3.7/site-packages/xarray/core/combine.py in _old_
˓→auto_combine(datasets, concat_dim, compat, data_vars, coords, fill_value, join)
917 join=join,
918 )
--> 919 for vars, datasets in grouped
920 ]
921 else:
~/miniconda3/envs/analysis/lib/python3.7/site-packages/xarray/core/combine.py in
˓→<listcomp>(.0)
917 join=join,
918 )
--> 919 for vars, datasets in grouped
920 ]
921 else:
~/miniconda3/envs/analysis/lib/python3.7/site-packages/xarray/core/combine.py in _
(continues on next page)
˓→auto_concat(datasets, dim, data_vars, coords, fill_value, join, compat)
1.1. Examples 47
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
953 elif len(concat_dims) == 0:
954 raise ValueError(
--> 955 "cannot infer dimension to concatenate: "
956 "supply the ``concat_dim`` argument "
957 "explicitly"
ValueError: cannot infer dimension to concatenate: supply the ``concat_dim`` argument
˓→explicitly
[ ]:
1.1.6 Temperature and Salinity at Depth Levels
The goal of this notebook is the following:
1) serve as an example of how to post-process CESM/MOM6 output;
2) create time averages of T/S fields at depth levels and compared agains observations (PHC2);
/glade/p/cesm/omwg/obs_data/phc/PHC2_TEMP_tx0.66v1_34lev_ann_avg.nc
/glade/p/cesm/omwg/obs_data/phc/PHC2_SALT_tx0.66v1_34lev_ann_avg.nc
5) compare model results vs. another model results (TODO).
Temprature and salinity comparisons (model vs obs) at selected depth levels are grouped into the following regions:
Global, Antarctic, and Arctic.
[1]: %matplotlib inline
from mom6_tools.MOM6grid import MOM6grid
from mom6_tools.m6plot import xycompare, polarcomparison
from mom6_tools.DiagsCase import DiagsCase
from mom6_tools import m6toolbox
import yaml
import matplotlib.pyplot as plt
import numpy as np
import xarray as xr
from IPython.display import display, Markdown, Latex
import warnings
warnings.filterwarnings("ignore")
Basemap module not found. Some regional plots may not function properly
[2]: # 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)
[3]: # Create the case instance
dcase = DiagsCase(diag_config_yml['Case'])
print('Casename is:', dcase.casename)
Casename is: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076
[4]: # Load the grid
grd = dcase.grid
48 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
MOM6 grid successfully loaded...
[5]: parallel, cluster, client = m6toolbox.request_workers(6)
Requesting 6 workers...
/proxy/38119/status
[15]: client
[15]: <Client: not connected>
[16]: # Compute the climatology dataset
#dset_climo = climo.stage()
variables = ['thetao', 'so', 'time', 'time_bnds']
RUNDIR = dcase.get_value('RUNDIR')
def preprocess(ds):
''' Compute montly averages and return the dataset with variables'''
return ds[variables].resample(time="1Y", closed='left', \
keep_attrs=True).mean(dim='time', keep_attrs=True)
ds = xr.open_mfdataset(RUNDIR+'/'+dcase.casename+'.mom6.h_*.nc', \
parallel=True, data_vars='minimal', \
coords='minimal', compat='override', preprocess=preprocess)
[8]: # load model output, averaged over 20 years
#out = dset_climo['20Y']
start_date = '0001-01-01'
end_date = '0058-12-31'
%time ds = ds.sel(time=slice(start_date, end_date))
CPU times: user 4.9 ms, sys: 973 µs, total: 5.87 ms
Wall time: 5.33 ms
[9]: print('Time averaging...')
%time
temp = np.ma.masked_invalid(ds.thetao.mean('time').values)
salt = np.ma.masked_invalid(ds.so.mean('time').values)
Time averaging...
CPU times: user 3 µs, sys: 0 ns, total: 3 µs
Wall time: 4.53 µs
[10]: client.close(); cluster.close()
[11]: # load PHC2 data
phc_path = '/glade/p/cesm/omwg/obs_data/phc/'
phc_temp = xr.open_mfdataset(phc_path+'PHC2_TEMP_tx0.66v1_34lev_ann_avg.nc', decode_
˓→coords=False, decode_times=False)
phc_salt = xr.open_mfdataset(phc_path+'PHC2_SALT_tx0.66v1_34lev_ann_avg.nc', decode_
˓→coords=False, decode_times=False)
1.1. Examples 49
mom6-tools Documentation, Release 0.0.post86
Global
[17]: %matplotlib inline
km = len(phc_temp['depth'])
for k in range(km):
if ds['z_l'][k].values < 100.0:
temp_obs = np.ma.masked_invalid(phc_temp['TEMP'][k,:].values)
xycompare(temp[k,:] , temp_obs, grd.geolon, grd.geolat, area=grd.area_t,
title1 = 'model temperature, depth ='+str(ds['z_l'][k].values)+ 'm',
title2 = 'observed temperature, depth ='+str(phc_temp['depth'][k].
˓→values)+ 'm',
suptitle=dcase.casename + ', averaged '+str(start_date)+ ' and ' +str(end_
˓→date),
clim=(-1.9,30.), dcolormap=plt.cm.bwr,
extend='both', dextend='neither', dlim=(-2,2),
show= True)
salt_obs = np.ma.masked_invalid(phc_salt['SALT'][k,:].values)
xycompare( salt[k,:] , salt_obs, grd.geolon, grd.geolat, area=grd.area_t,
title1 = 'model salinity, depth ='+str(ds['z_l'][k].values)+ 'm',
title2 = 'observed salinity, depth ='+str(phc_temp['depth'][k].values)+ 'm
˓→',
suptitle=dcase.casename, clim=(30,39.), dcolormap=plt.cm.bwr,
extend='both', dextend='neither', dlim=(-2,2),
show= True)
50 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 51
mom6-tools Documentation, Release 0.0.post86
52 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 53
mom6-tools Documentation, Release 0.0.post86
54 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 55
mom6-tools Documentation, Release 0.0.post86
56 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 57
mom6-tools Documentation, Release 0.0.post86
58 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 59
mom6-tools Documentation, Release 0.0.post86
60 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 61
mom6-tools Documentation, Release 0.0.post86
62 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
Antarctic
[18]: # loop over depths and compare TS fields
km = len(phc_temp['depth'])
for k in range(km):
if (ds['z_l'][k].values < 100.):
temp_obs = np.ma.masked_invalid(phc_temp['TEMP'][k,:].values)
polarcomparison(temp[k,:] , temp_obs, grd,
title1 = 'model temperature, depth ='+str(ds['z_l'][k].values)+ 'm',
title2 = 'observed temperature, depth ='+str(phc_temp['depth'][k].
˓→values)+ 'm',
extend='both', dextend='neither', clim=(-1.9,10.5), dlim=(-2,2),
˓→dcolormap=plt.cm.bwr,
suptitle=dcase.casename + ', averaged '+str(start_date)+ ' to '
˓→+str(end_date),
proj='SP', show= True)
salt_obs = np.ma.masked_invalid(phc_salt['SALT'][k,:].values)
polarcomparison( salt[k,:] , salt_obs, grd,
title1 = 'model salinity, depth ='+str(ds['z_l'][k].values)+ 'm',
title2 = 'observed salinity, depth ='+str(phc_temp['depth'][k].values)+
˓→'m',
extend='both', dextend='neither', clim=(33.,35.), dlim=(-2,2),
˓→dcolormap=plt.cm.bwr,
suptitle=dcase.casename + ', averaged '+str(start_date)+ ' to '
˓→+str(end_date),
proj='SP', show= True)
1.1. Examples 63
mom6-tools Documentation, Release 0.0.post86
64 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 65
mom6-tools Documentation, Release 0.0.post86
66 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 67
mom6-tools Documentation, Release 0.0.post86
68 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 69
mom6-tools Documentation, Release 0.0.post86
70 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 71
mom6-tools Documentation, Release 0.0.post86
72 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 73
mom6-tools Documentation, Release 0.0.post86
74 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 75
mom6-tools Documentation, Release 0.0.post86
Arctic
[19]: # loop over depths and compare TS fields
km = len(phc_temp['depth'])
for k in range(km):
if (ds['z_l'][k].values < 100.):
temp_obs = np.ma.masked_invalid(phc_temp['TEMP'][k,:].values)
polarcomparison(temp[k,:] , temp_obs, grd,
title1 = 'model temperature, depth ='+str(ds['z_l'][k].values)+ 'm',
title2 = 'observed temperature, depth ='+str(phc_temp['depth'][k].
˓→values)+ 'm',
extend='both', dextend='neither', clim=(-1.9,10.5), dlim=(-2,2),
˓→dcolormap=plt.cm.bwr,
suptitle=dcase.casename + ', averaged '+str(start_date)+ ' to ' +str(end_
˓→date),
proj='NP', show= True)
salt_obs = np.ma.masked_invalid(phc_salt['SALT'][k,:].values)
polarcomparison( salt[k,:] , salt_obs, grd,
title1 = 'model salinity, depth ='+str(ds['z_l'][k].values)+ 'm',
title2 = 'observed salinity, depth ='+str(phc_temp['depth'][k].values)+ 'm
˓→',
extend='both', dextend='neither', clim=(32.,34.5), dlim=(-2,2),
˓→dcolormap=plt.cm.bwr,
suptitle=dcase.casename + ', averaged '+str(start_date)+ ' to ' +str(end_
˓→date),
proj='NP', show= True)
76 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 77
mom6-tools Documentation, Release 0.0.post86
78 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 79
mom6-tools Documentation, Release 0.0.post86
80 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 81
mom6-tools Documentation, Release 0.0.post86
82 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 83
mom6-tools Documentation, Release 0.0.post86
84 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 85
mom6-tools Documentation, Release 0.0.post86
86 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 87
mom6-tools Documentation, Release 0.0.post86
88 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[ ]:
[ ]:
1.1.7 Equatorial Upperocean model vs. obs comparison
The goal of this notebook is the following:
1) serve as an example of how to post-process CESM/MOM6 output;
2) create time averages of T, S and VEL fields and compared agains observations (PHC2 and Johnson et al, 2002);
/glade/p/cesm/omwg/obs_data/phc/PHC2_TEMP_tx0.66v1_34lev_ann_avg.nc
/glade/p/cesm/omwg/obs_data/phc/PHC2_SALT_tx0.66v1_34lev_ann_avg.nc
/glade/p/cesm/omwg/obs_data/johnson_pmel/meanfit_m.nc
TODO: * Compare potential density plots; * compare model results vs. another model results (TODO);
[1]: %matplotlib inline
from mom6_tools.MOM6grid import MOM6grid
from mom6_tools.m6toolbox import shiftgrid, request_workers
from mom6_tools.m6plot import yzcompare, yzplot
from mom6_tools.DiagsCase import DiagsCase
import yaml
import matplotlib.pyplot as plt
import numpy as np
import xarray as xr
from IPython.display import display, Markdown, Latex
import warnings
warnings.filterwarnings("ignore")
Basemap module not found. Some regional plots may not function properly
[2]: # Read in the yaml file
diag_config_yml_path = "/glade/u/home/gmarques/libs/mom6-tools/docs/source/examples/
˓→diag_config.yml"
diag_config_yml = yaml.load(open(diag_config_yml_path,'r'), Loader=yaml.Loader)
[3]: # Create the case instance
dcase = DiagsCase(diag_config_yml['Case'])
print('Casename is:', dcase.casename)
Casename is: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076
[4]: # Load the grid
RUNDIR = dcase.get_value('RUNDIR')
grd = MOM6grid(RUNDIR+'/'+dcase.casename+'.mom6.static.nc', xrformat=True)
grd_eq = grd.sel(yh=slice(-10,10))
MOM6 grid successfully loaded...
[5]: parallel, cluster, client = request_workers(6)
1.1. Examples 89
mom6-tools Documentation, Release 0.0.post86
Requesting 6 workers...
/proxy/8787/status
[6]: client
[6]: <Client: 'tcp://10.148.10.19:32847' processes=0 threads=0, memory=0 B>
[7]: # Compute the climatology dataset
#dset_climo = climo.stage()
variables = ['thetao', 'so', 'uo', 'time', 'time_bnds', 'e']
RUNDIR = dcase.get_value('RUNDIR')
def preprocess(ds):
''' Compute yearly averages and return the dataset with variables'''
return ds[variables].resample(time="1Y", closed='left', \
keep_attrs=True).mean(dim='time', keep_attrs=True)
ds = xr.open_mfdataset(RUNDIR+'/'+dcase.casename+'.mom6.h_*.nc', \
parallel=True, data_vars='minimal', \
coords='minimal', compat='override', preprocess=preprocess)
[8]: # load obs
phc_path = '/glade/p/cesm/omwg/obs_data/phc/'
phc_temp = xr.open_mfdataset(phc_path+'PHC2_TEMP_tx0.66v1_34lev_ann_avg.nc')#.
˓→sel(Y=slice(-10,10))
phc_salt = xr.open_mfdataset(phc_path+'PHC2_SALT_tx0.66v1_34lev_ann_avg.nc')#.
˓→sel(Y=slice(-10,10))
johnson = xr.open_dataset('/glade/p/cesm/omwg/obs_data/johnson_pmel/meanfit_m.nc')
[9]: # get theta and salt and rename coordinates to be the same as the model's
thetao_obs = phc_temp.TEMP.rename({'X': 'xh','Y': 'yh', 'depth': 'z_l'});
salt_obs = phc_salt.SALT.rename({'X': 'xh','Y': 'yh', 'depth': 'z_l'});
[10]: # set coordinates to the same as the model's
thetao_obs['xh'] = ds.xh; thetao_obs['yh'] = ds.yh;
salt_obs['xh'] = ds.xh; salt_obs['yh'] = ds.yh;
[11]: # select in space and time
avg = diag_config_yml['Avg']
start_date = avg['start_date']
end_date = avg['end_date']
%time ds = ds.sel(time=slice(start_date, end_date)).sel(yh=slice(-10,10)).isel(z_
˓→i=slice(0,15)).isel(z_l=slice(0,14))
CPU times: user 14.5 ms, sys: 0 ns, total: 14.5 ms
Wall time: 14 ms
[12]: print('Time averaging...')
thetao = ds.thetao.mean('time')
so = ds.so.mean('time')
uo = ds.uo.mean('time')
eta = ds.e.mean('time')
90 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
Time averaging...
[13]: print('Selecting equatorial data...')
# find point closest to eq. and select data
j = np.abs( grd_eq.geolat[:,0].values - 0. ).argmin()
temp_eq = np.ma.masked_invalid(thetao.isel(yh=j).values)
salt_eq = np.ma.masked_invalid(so.isel(yh=j).values)
u_eq = np.ma.masked_invalid(uo.isel(yh=j).values)
e_eq = np.ma.masked_invalid(eta.isel(yh=j).values)
thetao_obs_eq = np.ma.masked_invalid(thetao_obs.sel(yh=slice(-10,10)).isel(yh=j).
˓→isel(z_l=slice(0,14)).values)
salt_obs_eq = np.ma.masked_invalid(salt_obs.sel(yh=slice(-10,10)).isel(yh=j).isel(z_
˓→l=slice(0,14)).values)
Selecting equatorial data...
[14]: client.close(); cluster.close()
[15]: y = ds.yh.values
zz = ds.z_i.values
x = ds.xh.values
[X, Z] = np.meshgrid(x, zz)
z = 0.5 * ( Z[:-1] + Z[1:])
[16]: %matplotlib inline
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(14,16))
yzcompare(temp_eq , thetao_obs_eq, x, -Z,
title1 = 'model temperature',
title2 = 'observed temperature (PHC/Levitus)', axis=ax,
suptitle=dcase.casename + ', averaged '+str(start_date)+ ' to ' +str(end_
˓→date),
extend='neither', dextend='neither', clim=(6,31.), dlim=(-5,5), dcolormap=plt.
˓→cm.bwr)
1.1. Examples 91
mom6-tools Documentation, Release 0.0.post86
92 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[17]: %matplotlib inline
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(12,16))
yzcompare(salt_eq , salt_obs_eq, x, -Z,
title1 = 'model salinity',
title2 = 'observed salinity (PHC/Levitus)', axis=ax,
suptitle=dcase.casename + ', averaged '+str(start_date)+ ' to ' +str(end_
˓→date),
extend='neither', dextend='neither', clim=(33.5,37.), dlim=(-1,1),
˓→dcolormap=plt.cm.bwr)
1.1. Examples 93
mom6-tools Documentation, Release 0.0.post86
94 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[18]: %matplotlib inline
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(12,8))
yzplot(temp_eq, x, -Z, axis=ax, clim=(5,31), landcolor=[0., 0., 0.], ignore=np.nan)
cs1 = ax.contour( x + 0*z, -z, temp_eq, colors='k',); plt.clabel(cs1,fmt='%2.1f',
˓→fontsize=14)
plt.ylim(-400,0)
[18]: (-400, 0)
[19]: fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(12,8))
yzplot(thetao_obs_eq, x, -Z, axis=ax, clim=(5,31))
cs1 = ax.contour( x + 0*z, -z, thetao_obs_eq, colors='k',); plt.clabel(cs1,fmt='%2.1f
˓→', fontsize=14)
ax.set_ylim(-400,0)
[19]: (-400, 0)
1.1. Examples 95
mom6-tools Documentation, Release 0.0.post86
[20]: # Shift model data to compare against obs
tmp, lonh = shiftgrid(thetao.xh[-1].values, thetao[0,0,:].values, ds.thetao.xh.values)
tmp, lonq = shiftgrid(uo.xq[-1].values, uo[0,0,:].values, uo.xq.values)
thetao['xh'].values[:] = lonh
so['xh'].values[:] = lonh
uo['xq'].values[:] = lonq
[21]: # y and z from obs
y_obs = johnson.YLAT11_101.values
zz = np.arange(0,510,10)
[Y, Z_obs] = np.meshgrid(y_obs, zz)
z_obs = 0.5 * ( Z_obs[0:-1,:] + Z_obs[1:,] )
[22]: # y and z from model
y_model = thetao.yh.values
z = eta.z_i.values
[Y, Z_model] = np.meshgrid(y_model, z)
z_model = 0.5 * ( Z_model[0:-1,:] + Z_model[1:,:] )
[23]: longitudes = [143., 156., 165., 180., 190., 205., 220., 235., 250., 265.]
[24]: # Temperature
for l in longitudes:
(continues on next page)
96 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(16,8))
dummy_model = np.ma.masked_invalid(thetao.sel(xh=l, method='nearest').values)
dummy_obs = np.ma.masked_invalid(johnson.POTEMPM.sel(XLON=l, method='nearest').
˓→values)
yzplot(dummy_model, y_model, -Z_model, clim=(9,29), axis=ax1, zlabel='Depth',
˓→ylabel='Latitude', title=str(dcase.casename))
cs1 = ax1.contour( y_model + 0*z_model, -z_model, dummy_model, levels=np.arange(0,
˓→30,2), colors='k',); plt.clabel(cs1,fmt='%3.1f', fontsize=14)
ax1.set_ylim(-400,0)
yzplot(dummy_obs, y_obs, -Z_obs, clim=(9,29), axis=ax2, zlabel='Depth', ylabel=
˓→'Latitude', title='Johnson et al (2002)')
cs2 = ax2.contour( y_obs + 0*z_obs, -z_obs, dummy_obs, levels=np.arange(0,30,2),
˓→colors='k',); plt.clabel(cs2,fmt='%3.1f', fontsize=14)
ax2.set_ylim(-400,0)
plt.suptitle('Temperature [C] @ '+str(l)+ ', averaged between '+str(start_date)+'
˓→and '+str(end_date))
1.1. Examples 97
mom6-tools Documentation, Release 0.0.post86
98 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 99
mom6-tools Documentation, Release 0.0.post86
100 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 101
mom6-tools Documentation, Release 0.0.post86
[25]: for l in longitudes:
# Salt
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(16,8))
dummy_model = np.ma.masked_invalid(so.sel(xh=l, method='nearest').values)
dummy_obs = np.ma.masked_invalid(johnson.SALINITYM.sel(XLON=l, method='nearest').
˓→values)
yzplot(dummy_model, y_model, -Z_model, clim=(32,36), axis=ax1, zlabel='Depth',
˓→ylabel='Latitude', title=str(dcase.casename))
cs1 = ax1.contour( y_model + 0*z_model, -z_model, dummy_model, levels=np.
˓→arange(32,36,0.5), colors='k',); plt.clabel(cs1,fmt='%3.1f', fontsize=14)
ax1.set_ylim(-400,0)
yzplot(dummy_obs, y_obs, -Z_obs, clim=(32,36), axis=ax2, zlabel='Depth', ylabel=
˓→'Latitude', title='Johnson et al (2002)')
cs2 = ax2.contour( y_obs + 0*z_obs, -z_obs, dummy_obs, levels=np.arange(32,36,0.
˓→5), colors='k',); plt.clabel(cs2,fmt='%3.1f', fontsize=14)
ax2.set_ylim(-400,0)
plt.suptitle('Salinity [psu] @ '+str(l)+ ', averaged between '+str(start_date)+'
˓→and '+str(end_date))
102 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 103
mom6-tools Documentation, Release 0.0.post86
104 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 105
mom6-tools Documentation, Release 0.0.post86
106 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[26]: for l in longitudes:
# uo
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(16,8))
dummy_model = np.ma.masked_invalid(uo.sel(xq=l, method='nearest').values)
dummy_obs = np.ma.masked_invalid(johnson.UM.sel(XLON=l, method='nearest').values)
yzplot(dummy_model, y_model, -Z_model, clim=(-1,1), axis=ax1, zlabel='Depth',
˓→ylabel='Latitude', title=str(dcase.casename))
cs1 = ax1.contour( y_model + 0*z_model, -z_model, dummy_model, levels=np.arange(-
˓→1,1,0.1), colors='k',); plt.clabel(cs1,fmt='%3.1f', fontsize=14)
(continues on next page)
1.1. Examples 107
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
ax1.set_ylim(-400,0)
yzplot(dummy_obs, y_obs, -Z_obs, clim=(-1,1), axis=ax2, zlabel='Depth', ylabel=
˓→'Latitude', title='Johnson et al (2002)')
cs2 = ax2.contour( y_obs + 0*z_obs, -z_obs, dummy_obs, levels=np.arange(-1,1,0.1),
˓→ colors='k',); plt.clabel(cs2,fmt='%3.1f', fontsize=14)
ax2.set_ylim(-400,0)
plt.suptitle('Eastward velocity [m/s] @ '+str(l)+ ', averaged between '+str(start_
˓→date)+' and '+str(end_date))
108 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 109
mom6-tools Documentation, Release 0.0.post86
110 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 111
mom6-tools Documentation, Release 0.0.post86
[27]: x_obs = johnson.XLON.values
[X_obs, Z_obs] = np.meshgrid(x_obs, zz)
z_obs = 0.5 * ( Z_obs[:-1,:] + Z_obs[1:,:] )
[28]: x_model = so.xh.values
z = eta.z_i.values
[X, Z_model] = np.meshgrid(x_model, z)
z_model = 0.5 * ( Z_model[:-1,:] + Z_model[1:,:] )
112 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[32]: #from mom6_tools.m6plot import
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(16,8))
dummy_obs = np.ma.masked_invalid(johnson.UM.sel(YLAT11_101=0).values)
dummy_model = np.ma.masked_invalid(uo.sel(yh=0, method='nearest').values)
yzplot(dummy_model, x_model, -Z_model, clim=(-0.4,1.2), axis=ax1, landcolor=[0., 0.,
˓→0.], title=str(dcase.casename), ylabel='Longitude', yunits=r'$^o$E' )
cs1 = ax1.contour( x_model + 0*z_model, -z_model, dummy_model, levels=np.arange(-1.2,
˓→1.2,0.1), colors='k',); plt.clabel(cs1,fmt='%2.1f', fontsize=14)
ax1.set_xlim(143,265); ax1.set_ylim(-400,0)
yzplot(dummy_obs, x_obs, -Z_obs, clim=(-0.4,1.2), axis=ax2, title='Johnson et al
˓→(2002)', ylabel='Longitude', yunits=r'$^o$E' )
cs1 = ax2.contour( x_obs + 0*z_obs, -z_obs, dummy_obs, levels=np.arange(-1.2,1.2,0.
˓→1), colors='k',); plt.clabel(cs1,fmt='%2.1f', fontsize=14)
ax2.set_xlim(143,265); ax2.set_ylim(-400,0)
plt.suptitle('Eastward velocity [m/s] along the Equatorial Pacific, averaged between
˓→'+str(start_date)+' and '+str(end_date))
[32]: Text(0.5, 0.98, 'Eastward velocity [m/s] along the Equatorial Pacific, averaged
˓→between 0029-01-01 and 0059-01-01')
[ ]:
1.1.8 Globally Averaged Ocean Temperature and Salinity
[1]: from mom6_tools.DiagsCase import DiagsCase
import yaml
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import xarray as xr
1.1. Examples 113
mom6-tools Documentation, Release 0.0.post86
[2]: # Read in the yaml file
diag_config_yml_path = "/glade/u/home/gmarques/libs/mom6-tools/docs/source/examples/
˓→diag_config.yml"
diag_config_yml = yaml.load(open(diag_config_yml_path,'r'), Loader=yaml.Loader)
[3]: # Create the case instance
dcase = DiagsCase(diag_config_yml['Case'])
print('Casename is:', dcase.casename)
RUNDIR = dcase.get_value('RUNDIR')
print('RUNDIR:', RUNDIR)
Casename is: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076
RUNDIR: /glade/scratch/gmarques/g.c2b6.GJRA.TL319_t061.long_JRA_mct.076/run
[4]: # load data
ds = xr.open_mfdataset(RUNDIR+'/*.mom6.hm_*nc',decode_times=False)
Time series
[5]: matplotlib.rcParams.update({'font.size': 18})
fig, axes = plt.subplots(nrows=2, figsize=(16, 8))
ax = axes[0]
ax.plot(ds.time.data/365., ds.thetaoga[:,0].data)
ax.set_ylabel(r'$^o$C')
ax.set_title("Global average temperature")
fig.autofmt_xdate()
ax = axes[1]
ax.plot(ds.time.data/365., ds.soga[:,0].data)
ax.set_title("Global average salinity")
ax.set_ylabel('PSU')
ax.set_ylim(ds.soga.min(),ds.soga.max())
ax.set_xlabel('Year')
fig.autofmt_xdate()
114 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[ ]:
1.1.9 Meridional Overturning
mom6_tools.moc functions for computing and plotting meridional overturning.
The goal of this notebook is the following:
1) server as an example on to compute a meridional overturning streamfunction (global and Atalntic) from
CESM/MOM output;
2) evaluate model experiments by comparing transports against observed estimates and other model results.
[1]: %matplotlib inline
import matplotlib
import numpy as np
import xarray as xr
# mom6_tools
from mom6_tools.moc import *
from mom6_tools.DiagsCase import DiagsCase
from mom6_tools.m6toolbox import request_workers, genBasinMasks, add_global_attrs
import matplotlib.pyplot as plt
import warnings, yaml, os
warnings.filterwarnings("ignore")
Basemap module not found. Some regional plots may not function properly
[2]: # Read in the yaml file
diag_config_yml_path = "/glade/u/home/gmarques/libs/mom6-tools/docs/source/examples/
˓→diag_config.yml"
diag_config_yml = yaml.load(open(diag_config_yml_path,'r'), Loader=yaml.Loader)
# Create the case instance
dcase = DiagsCase(diag_config_yml['Case'])
RUNDIR = dcase.get_value('RUNDIR')
print('Run directory is:', RUNDIR)
print('Casename is:', dcase.casename)
Run directory is: /glade/scratch/gmarques/g.c2b6.GJRA.TL319_t061.long_JRA_mct.076/run
Casename is: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076
[3]: # The following parameters must be set accordingly
######################################################
# add your name and email address below
author = 'Gustavo Marques (
[email protected])'
######################################################
# create an empty class object
class args:
pass
args.infile = RUNDIR
args.monthly = dcase.casename+'.mom6.h_*nc'
args.sigma2 = dcase.casename+'.mom6.rho2_*nc'
args.start_date = ''
args.end_date = ''
args.case_name = dcase.casename
(continues on next page)
1.1. Examples 115
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
args.label = ''
args.savefigs = False
[4]: # set avg dates
avg = diag_config_yml['Avg']
if not args.start_date : args.start_date = avg['start_date']
if not args.end_date : args.end_date = avg['end_date']
[5]: # Load the grid
grd = dcase.grid
depth = grd.depth_ocean
# remove Nan's, otherwise genBasinMasks won't work
depth[np.isnan(depth)] = 0.0
basin_code = genBasinMasks(grd.geolon, grd.geolat, depth, verbose=False)
MOM6 grid successfully loaded...
11.16427964664149 64.78854837178643 [391, 434]
[6]: parallel, cluster, client = m6toolbox.request_workers(6)
Requesting 6 workers...
/proxy/43847/status
[7]: client
[7]: <Client: 'tcp://10.148.10.19:45211' processes=0 threads=0, memory=0 B>
[8]: def preprocess(ds):
variables = ['vmo','vhml','vhGM']
for v in variables:
if v not in ds.variables:
ds[v] = xr.zeros_like(ds.vo)
return ds[variables]
[9]: print('\n Reading dataset...')
# load data
%time ds = xr.open_mfdataset(RUNDIR+'/'+dcase.casename+'.mom6.h_*.nc', parallel=True,
˓→\
combine="nested", concat_dim="time",
˓→preprocess=preprocess).chunk({"time": 12})
Reading dataset...
CPU times: user 1.6 s, sys: 185 ms, total: 1.78 s
Wall time: 27.5 s
[10]: # compute yearly means first since this will be used in the time series
print('\n Computing yearly means...')
%time ds_yr = ds.resample(time="1Y", closed='left').mean('time')
Computing yearly means...
CPU times: user 1.15 s, sys: 11.4 ms, total: 1.16 s
Wall time: 1.14 s
116 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[11]: print('\n Selecting data between {} and {}...'.format(args.start_date, args.end_date))
%time ds_sel = ds_yr.sel(time=slice(args.start_date, args.end_date))
Selecting data between 0029-01-01 and 0059-01-01...
CPU times: user 13.4 ms, sys: 0 ns, total: 13.4 ms
Wall time: 11.9 ms
[12]: print('\n Computing time mean...')
%time ds_mean = ds_sel.mean('time').compute()
Computing time mean...
CPU times: user 2.04 s, sys: 412 ms, total: 2.45 s
Wall time: 11.8 s
[14]: stream = True
# create a ndarray subclass
class C(np.ndarray): pass
if 'vmo' in ds.variables:
varName = 'vmo'; conversion_factor = 1.e-9
elif 'vh' in ds.variables:
varName = 'vh'; conversion_factor = 1.e-6
if 'zw' in ds.variables: conversion_factor = 1.e-9 # Backwards compatible for when
˓→we had wrong units for 'vh'
else: raise Exception('Could not find "vh" or "vmo" in file "%s"'%(args.infile+args.
˓→static))
tmp = np.ma.masked_invalid(ds_mean[varName].values)
tmp = tmp[:].filled(0.)
VHmod = tmp.view(C)
VHmod.units = ds[varName].units
Zmod = m6toolbox.get_z(ds, depth, varName)
if args.case_name != '': case_name = args.case_name + ' ' + args.label
else: case_name = rootGroup.title + ' ' + args.label
Global MOC
[15]: %matplotlib inline
# Global MOC
m6plot.setFigureSize([16,9],576,debug=False)
axis = plt.gca()
cmap = plt.get_cmap('dunnePM')
zg = Zmod.min(axis=-1); psiPlot = MOCpsi(VHmod)*conversion_factor
psiPlot = 0.5 * (psiPlot[0:-1,:]+psiPlot[1::,:])
yyg = grd.geolat_c[:,:].max(axis=-1)+0*zg
ci=m6plot.pmCI(0.,40.,5.)
plotPsi(yyg, zg, psiPlot, ci, 'Global MOC [Sv]')
(continues on next page)
1.1. Examples 117
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
plt.xlabel(r'Latitude [$\degree$N]')
plt.suptitle(case_name)
plt.gca().invert_yaxis()
findExtrema(yyg, zg, psiPlot, max_lat=-30.)
findExtrema(yyg, zg, psiPlot, min_lat=25., min_depth=250.)
findExtrema(yyg, zg, psiPlot, min_depth=2000., mult=-1.)
[16]: # create dataset to store results
moc = xr.Dataset(data_vars={ 'moc' : (('z_l','yq'), psiPlot),
'amoc' : (('z_l','yq'), np.zeros((psiPlot.shape))),
'moc_FFM' : (('z_l','yq'), np.zeros((psiPlot.shape))),
'moc_GM' : (('z_l','yq'), np.zeros((psiPlot.shape))),
'amoc_45' : (('time'), np.zeros((ds_yr.time.shape))),
'moc_GM_ACC' : (('time'), np.zeros((ds_yr.time.shape))),
'amoc_26' : (('time'), np.zeros((ds_yr.time.shape))) },
coords={'z_l': ds.z_l, 'yq':ds.yq, 'time':ds_yr.time})
attrs = {'description': 'MOC time-mean sections and time-series', 'unit': 'Sv',
˓→'start_date': avg['start_date'],
'end_date': avg['end_date']}
add_global_attrs(moc,attrs)
Atlantic MOC
[18]: m6plot.setFigureSize([16,9],576,debug=False)
cmap = plt.get_cmap('dunnePM')
m = 0*basin_code; m[(basin_code==2) | (basin_code==4) | (basin_code==6) | (basin_
˓→code==7) | (basin_code==8)]=1
ci=m6plot.pmCI(0.,22.,2.)
(continues on next page)
118 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
z = (m*Zmod).min(axis=-1); psiPlot = MOCpsi(VHmod, vmsk=m*np.roll(m,-1,axis=-
˓→2))*conversion_factor
psiPlot = 0.5 * (psiPlot[0:-1,:]+psiPlot[1::,:])
yy = grd.geolat_c[:,:].max(axis=-1)+0*z
plotPsi(yy, z, psiPlot, ci, 'Atlantic MOC [Sv]')
plt.xlabel(r'Latitude [$\degree$N]')
plt.suptitle(case_name)
plt.gca().invert_yaxis()
findExtrema(yy, z, psiPlot, min_lat=26.5, max_lat=27., min_depth=250.) # RAPID
findExtrema(yy, z, psiPlot, min_lat=44, max_lat=46., min_depth=250.) # RAPID
findExtrema(yy, z, psiPlot, max_lat=-33.)
findExtrema(yy, z, psiPlot)
findExtrema(yy, z, psiPlot, min_lat=5.)
moc['amoc'].data = psiPlot
AMOC profile at 26N
[19]: rapid_vertical = xr.open_dataset('/glade/work/gmarques/cesm/datasets/RAPID/moc_
˓→vertical.nc')
[20]: if 'zl' in ds:
zl=ds.zl.values
elif 'z_l' in ds:
zl=ds.z_l.values
else:
raise ValueError("Dataset does not have vertical coordinate zl or z_l")
1.1. Examples 119
mom6-tools Documentation, Release 0.0.post86
[21]: fig, ax = plt.subplots(nrows=1, ncols=1)
ax.plot(rapid_vertical.stream_function_mar.mean('time'), rapid_vertical.depth, 'k',
˓→label='RAPID')
ax.plot(moc['amoc'].sel(yq=26, method='nearest'), moc.z_l, label=case_name)
ax.legend()
plt.gca().invert_yaxis()
plt.grid()
ax.set_xlabel('AMOC @ 26N [Sv]')
ax.set_ylabel('Depth [m]')
[21]: Text(0, 0.5, 'Depth [m]')
AMOC time series
[24]: dtime = ds_yr.time.values
amoc_26 = np.zeros(len(dtime))
amoc_45 = np.zeros(len(dtime))
moc_GM_ACC = np.zeros(len(dtime))
# loop in time
for t in range(len(dtime)):
tmp = np.ma.masked_invalid(ds_yr[varName].sel(time=dtime[t]).values)
tmp = tmp[:].filled(0.)
psi = MOCpsi(tmp, vmsk=m*np.roll(m,-1,axis=-2))*conversion_factor
psi = 0.5 * (psi[0:-1,:]+psi[1::,:])
amoc_26[t] = findExtrema(yy, z, psi, min_lat=26.5, max_lat=27., plot=False)
amoc_45[t] = findExtrema(yy, z, psi, min_lat=44., max_lat=46., plot=False)
tmp_GM = np.ma.masked_invalid(ds_yr['vhGM'][t,:].values)
tmp_GM = tmp_GM[:].filled(0.)
psiGM = MOCpsi(tmp_GM)*conversion_factor
psiGM = 0.5 * (psiGM[0:-1,:]+psiGM[1::,:])
moc_GM_ACC[t] = findExtrema(yyg, zg, psiGM, min_lat=-65., max_lat=-30, mult=-1.,
˓→plot=False)
[25]: # add dataarays to the moc dataset
moc['amoc_26'].data = amoc_26
(continues on next page)
120 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
moc['amoc_45'].data = amoc_45
moc['moc_GM_ACC'].data = moc_GM_ACC
[26]: moc['moc_GM_ACC'].plot()
[26]: [<matplotlib.lines.Line2D at 0x2b78932e5d30>]
AMOC @ 26 𝑜 N
[27]: # load AMOC time series data (5th) cycle used in Danabasoglu et al., doi:10.1016/j.
˓→ocemod.2015.11.007
path = '/glade/p/cesm/omwg/amoc/COREII_AMOC_papers/papers/COREII.variability/data.
˓→original/'
amoc_core_26 = xr.open_dataset(path+'AMOCts.cyc5.26p5.nc')
# load AMOC from POP JRA-55
amoc_pop_26 = xr.open_dataset('/glade/u/home/bryan/MOM6-modeloutputanalysis/'
'AMOC_series_26n.g210.GIAF_JRA.v13.gx1v7.01.nc')
# load RAPID time series
rapid = xr.open_dataset('/glade/work/gmarques/cesm/datasets/RAPID/moc_transports.nc').
˓→resample(time="1Y",
closed='left',keep_attrs=True).mean('time',keep_
˓→attrs=True)
# plot
fig = plt.figure(figsize=(12, 6))
plt.plot(np.arange(len(moc.time))+1958.5 ,moc['amoc_26'].values, color='k',
˓→label=case_name, lw=2)
# core data
core_mean = amoc_core_26['MOC'].mean(axis=0).data
core_std = amoc_core_26['MOC'].std(axis=0).data
plt.plot(amoc_core_26.time,core_mean, 'k', label='CORE II (group mean)', color='
˓→#1B2ACC', lw=1)
plt.fill_between(amoc_core_26.time, core_mean-core_std, core_mean+core_std,
alpha=0.25, edgecolor='#1B2ACC', facecolor='#089FFF')
# pop data
plt.plot(np.arange(len(amoc_pop_26.time))+1958.5 ,amoc_pop_26.AMOC_26n.values, color=
˓→'r', label='POP', lw=1)
(continues on next page)
1.1. Examples 121
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
# rapid
plt.plot(np.arange(len(rapid.time))+2004.5 ,rapid.moc_mar_hc10.values, color='green',
˓→label='RAPID', lw=1)
plt.title('AMOC @ 26 $^o$ N', fontsize=16)
plt.ylim(5,20)
plt.xlim(1948,1958.5+len(moc.time))
plt.xlabel('Time [years]', fontsize=16); plt.ylabel('Sv', fontsize=16)
plt.legend(fontsize=13, ncol=2)
[27]: <matplotlib.legend.Legend at 0x2b78937566d8>
AMOC @ 45 𝑜 N
[29]: amoc_core_45 = xr.open_dataset(path+'AMOCts.cyc5.45.nc')
amoc_pop_45 = xr.open_dataset('/glade/u/home/bryan/MOM6-modeloutputanalysis/'
'AMOC_series_45n.g210.GIAF_JRA.v13.gx1v7.01.nc')
# plot
fig = plt.figure(figsize=(12, 6))
plt.plot(np.arange(len(moc.time))+1958.5 ,moc['amoc_45'].values, color='k',
˓→label=case_name, lw=2)
# core data
core_mean = amoc_core_45['MOC'].mean(axis=0).data
core_std = amoc_core_45['MOC'].std(axis=0).data
plt.plot(amoc_core_45.time,core_mean, 'k', label='CORE II (group mean)', color='
˓→#1B2ACC', lw=1)
plt.fill_between(amoc_core_45.time, core_mean-core_std, core_mean+core_std,
alpha=0.25, edgecolor='#1B2ACC', facecolor='#089FFF')
# pop data
plt.plot(np.arange(len(amoc_pop_45.time))+1958. ,amoc_pop_45.AMOC_45n.values, color='r
˓→', label='POP', lw=1) (continues on next page)
122 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
plt.title('AMOC @ 45 $^o$ N', fontsize=16)
plt.ylim(5,20)
plt.xlim(1948,1958+len(moc.time))
plt.xlabel('Time [years]', fontsize=16); plt.ylabel('Sv', fontsize=16)
plt.legend(fontsize=13, ncol=3)
[29]: <matplotlib.legend.Legend at 0x2b78aaea6438>
Submesoscale-induced Global MOC
[31]: # create a ndarray subclass
class C(np.ndarray): pass
if 'vhml' in ds.variables:
varName = 'vhml'; conversion_factor = 1.e-9
else: raise Exception('Could not find "vhml" in file "%s"'%(args.infile+args.monthly))
tmp = np.ma.masked_invalid(ds_mean[varName].values)
tmp = tmp[:].filled(0.)
VHmod = tmp.view(C)
VHmod.units = ds[varName].units
# Global MOC
m6plot.setFigureSize([16,9],576,debug=False)
axis = plt.gca()
cmap = plt.get_cmap('dunnePM')
z = Zmod.min(axis=-1); psiPlot = MOCpsi(VHmod)*conversion_factor
psiPlot = 0.5 * (psiPlot[0:-1,:]+psiPlot[1::,:])
#yy = y[1:,:].max(axis=-1)+0*z
yy = grd.geolat_c[:,:].max(axis=-1)+0*z
(continues on next page)
1.1. Examples 123
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
ci=m6plot.pmCI(0.,20.,2.)
plotPsi(yy, z, psiPlot, ci, 'Global MOC [Sv] due to vhML', zval=[0.,-400.,-6500.])
plt.xlabel(r'Latitude [$\degree$N]')
plt.suptitle(case_name)
plt.gca().invert_yaxis()
moc['moc_FFM'].data = psiPlot
Eddy(GM)-induced Global MOC
[32]: # create a ndarray subclass
class C(np.ndarray): pass
if 'vhGM' in ds.variables:
varName = 'vhGM'; conversion_factor = 1.e-9
else: raise Exception('Could not find "vhGM" in file "%s"'%(args.infile+args.monthly))
tmp = np.ma.masked_invalid(ds_mean[varName].values)
tmp = tmp[:].filled(0.)
VHmod = tmp.view(C)
VHmod.units = ds[varName].units
# Global MOC
m6plot.setFigureSize([16,9],576,debug=False)
axis = plt.gca()
cmap = plt.get_cmap('dunnePM')
z = Zmod.min(axis=-1); psiPlot = MOCpsi(VHmod)*conversion_factor
psiPlot = 0.5 * (psiPlot[0:-1,:]+psiPlot[1::,:])
yy = grd.geolat_c[:,:].max(axis=-1)+0*z
(continues on next page)
124 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
ci=m6plot.pmCI(0.,20.,1.)
plotPsi(yy, z, psiPlot, ci, 'Global MOC [Sv] due to GM')
plt.xlabel(r'Latitude [$\degree$N]')
plt.suptitle(case_name)
findExtrema(yy, z, psiPlot, min_lat=-65., max_lat=-30, mult=-1.)
plt.gca().invert_yaxis()
moc['moc_GM'].data = psiPlot
Sigma-2 space (to be implemented. . . )
[ ]: # load data
ds = xr.open_mfdataset(args.infile+args.sigma2,decode_times=False)
# create a ndarray subclass
class C(np.ndarray): pass
if 'vmo' in ds.variables:
varName = 'vmo'; conversion_factor = 1.e-9
elif 'vh' in ds.variables:
varName = 'vh'; conversion_factor = 1.e-6
if 'zw' in ds.variables: conversion_factor = 1.e-9 # Backwards compatible for when
˓→we had wrong units for 'vh'
else: raise Exception('Could not find "vh" or "vmo" in file "%s"'%(args.infile+args.
˓→static))
tmp = np.ma.masked_invalid(ds[varName].sel(time=slice(ti,tf)).mean('time').data)
tmp = tmp[:].filled(0.)
(continues on next page)
1.1. Examples 125
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
VHmod = tmp.view(C)
VHmod.units = ds[varName].units
Zmod = m6toolbox.get_z(ds, depth, varName)
if args.case_name != '': case_name = args.case_name + ' ' + args.label
else: case_name = rootGroup.title + ' ' + args.label
[34]: # release workers
client.close(); cluster.close()
[ ]:
1.1.10 Poleward Heat Transport
mom6_tools.polar_heat_transport collection of functions for computing and plotting poleward heat trans-
port.
The goal of this notebook is the following:
1) server as an example on to compute polar heat transport from CESM/MOM output;
2) evaluate model experiments by comparing transports against observed estimates;
3) compare model results vs. another model results (TODO).
[1]: %matplotlib inline
from mom6_tools.poleward_heat_transport import *
from mom6_tools.m6toolbox import genBasinMasks
from mom6_tools.DiagsCase import DiagsCase
import mom6_tools.m6toolbox
from datetime import datetime, date
import yaml
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import xarray as xr
import warnings
warnings.filterwarnings("ignore")
Basemap module not found. Some regional plots may not function properly
[2]: # Read in the yaml file
diag_config_yml_path = "/glade/u/home/gmarques/libs/mom6-tools/docs/source/examples/
˓→diag_config.yml"
diag_config_yml = yaml.load(open(diag_config_yml_path,'r'), Loader=yaml.Loader)
[3]: # Create the case instance
dcase = DiagsCase(diag_config_yml['Case'])
RUNDIR = dcase.get_value('RUNDIR')
print('Run directory is:', RUNDIR)
print('Casename is:', dcase.casename)
Run directory is: /glade/scratch/gmarques/g.c2b6.GJRA.TL319_t061.long_JRA_mct.076/run
Casename is: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076
126 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[4]: # create an empty class object
class args:
pass
args.case_name = dcase.casename
args.start_date = ''
args.end_date = ''
args.savefigs = False
[5]: # set avg dates
avg = diag_config_yml['Avg']
if not args.start_date : args.start_date = avg['start_date']
if not args.end_date : args.end_date = avg['end_date']
[6]: # Load the grid
grd = dcase.grid
depth = grd.depth_ocean
# remove Nan's, otherwise genBasinMasks won't work
depth[np.isnan(depth)] = 0.0
basin_code = genBasinMasks(grd.geolon, grd.geolat, depth, verbose=False)
MOM6 grid successfully loaded...
11.16427964664149 64.78854837178643 [391, 434]
[7]: parallel, cluster, client = m6toolbox.request_workers(6)
Requesting 6 workers...
/proxy/46825/status
[8]: client
[8]: <Client: 'tcp://10.148.10.19:40143' processes=0 threads=0, memory=0 B>
[9]: def preprocess(ds):
''' Compute montly averages and return the dataset with variables'''
ds
for var in variables:
print('Processing {}'.format(var))
if var not in ds.variables:
print('WARNING: ds does not have variable {}. Creating dataarray with zeros'.
˓→format(var))
jm, im = grd.geolat.shape
tm = len(ds.time)
da = xr.DataArray(numpy.zeros((tm, jm, im)), dims=['time', 'yq','xh'], \
coords={'yq' : grd.yq, 'xh' : grd.xh, 'time' : ds.time}).rename(var)
ds = xr.merge([ds, da])
return ds[variables]
[10]: print('\n Reading monthly (hm_*) dataset...')
# load data
variables = ['T_ady_2d', 'T_diffy_2d', 'T_lbd_diffy_2d']
%time ds = xr.open_mfdataset(RUNDIR+'/'+dcase.casename+'.mom6.hm_*.nc', \
parallel=True, data_vars='minimal', chunks={'time': 12},\
coords='minimal', compat='override', preprocess=preprocess)
1.1. Examples 127
mom6-tools Documentation, Release 0.0.post86
Reading monthly (hm_*) dataset...
CPU times: user 34.2 s, sys: 43.3 s, total: 1min 17s
Wall time: 1min 29s
[11]: 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)).load()
Selecting data between 0029-01-01 and 0059-01-01...
CPU times: user 5.52 s, sys: 2.35 s, total: 7.87 s
Wall time: 15.2 s
[12]: print('\n Computing yearly means...')
%time ds_sel = ds_sel.resample(time="1Y", closed='left',keep_attrs=True).mean('time',
˓→keep_attrs=True)
Computing yearly means...
CPU times: user 1.2 s, sys: 125 ms, total: 1.33 s
Wall time: 1.31 s
[13]: print('\n Computing time mean...')
%time ds_sel = ds_sel.mean('time').load()
Computing time mean...
CPU times: user 83.1 ms, sys: 15.3 ms, total: 98.4 ms
Wall time: 95 ms
[14]: # release workers
client.close(); cluster.close()
[16]: stream = True
# create a ndarray subclass
class C(np.ndarray): pass
varName = 'T_ady_2d'
if varName in ds.variables:
tmp = np.ma.masked_invalid(ds_sel[varName].values)
tmp = tmp[:].filled(0.)
advective = tmp.view(C)
advective.units = ds[varName].units
else:
raise Exception('Could not find "T_ady_2d" in ds')
varName = 'T_diffy_2d'
if varName in ds.variables:
tmp = np.ma.masked_invalid(ds_sel[varName].values)
tmp = tmp[:].filled(0.)
diffusive = tmp.view(C)
diffusive.units = ds[varName].units
else:
diffusive = None
warnings.warn('Diffusive temperature term not found. This will result in an
˓→underestimation of the heat transport.')
(continues on next page)
128 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
varName = 'T_lbd_diffy_2d'
if varName in ds.variables:
tmp = np.ma.masked_invalid(ds_sel[varName].values)
tmp = tmp[:].filled(0.)
lbd = tmp.view(C)
#lbd.units = ds[varName].units
else:
lbd = None
warnings.warn('Lateral boundary mixing term not found. This will result in an
˓→underestimation of the heat transport.')
[17]: %matplotlib inline
# plot model vs obs
plt_heat_transport_model_vs_obs(advective, diffusive, lbd, basin_code, grd, args)
1.1. Examples 129
mom6-tools Documentation, Release 0.0.post86
130 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[ ]:
1.1.11 Transport across sections
mom6_tools.section_transports collection of functions for computing and plotting time-series of transports
across vertical sections.
The goal of this notebook is the following:
1) server as an example on how to post-process the CESM/MOM6 vertical sections defined in diag_table. The
location of the current vertical sections computed online can be found at the end of this notebook;
2) evaluate model experiments by comparing transports against observed estimates;
3) compare model results vs. another model results (TODO).
1.1. Examples 131
mom6-tools Documentation, Release 0.0.post86
[1]: %matplotlib inline
from mom6_tools.section_transports import Transport, options
import matplotlib.pyplot as plt
from mom6_tools.DiagsCase import DiagsCase
import yaml
[2]: # Read in the yaml file
diag_config_yml_path = "/glade/u/home/gmarques/libs/mom6-tools/docs/source/examples/
˓→diag_config.yml"
diag_config_yml = yaml.load(open(diag_config_yml_path,'r'), Loader=yaml.Loader)
[3]: # Create the case instance
dcase = DiagsCase(diag_config_yml['Case'])
RUNDIR = dcase.get_value('RUNDIR')
print('Run directory is:', RUNDIR)
print('Casename is:', dcase.casename)
Run directory is: /glade/scratch/gmarques/g.c2b6.GJRA.TL319_t061.long_JRA_mct.076/run
Casename is: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076
[4]: # create an empty class object
class args:
pass
Define the arguments expected by class “Transport”. These have been hard-coded here fow now. . .
[5]: args.case_name = dcase.casename
path = "/glade/scratch/gmarques/"+dcase.casename+"/run/"
args.infile = path
# set avg dates
avg = diag_config_yml['Avg']
args.start_date = '0001-01-01' # override start date
args.end_date = avg['end_date']
args.label = ''
args.debug = False
Observed flows, more options can be added here
• Griffies et al., 2016: OMIP contribution to CMIP6: experimental and diagnostic protocol for the physical com-
ponent of the Ocean Model Intercomparison Project. Geosci. Model. Dev., 9, 3231-3296. doi:10.5194/gmd-9-
3231-2016
[6]: observedFlows = {'Agulhas':(129.8,143.6), 'Barents Opening':2.0, 'Bering Strait':(0.7,
˓→1.1), 'Davis Strait':(-2.1,-1.1), 'Denmark Strait':(-4.8,-2.0),
'Drake Passage':(129.8,143.6), 'English Channel':(0.01,0.1), 'Faroe-
˓→Scotland':(0.8,1.0), 'Florida-Bahamas':(28.9,34.3),
'Fram Strait':(-4.7,0.7), 'Gibraltar Strait':0.11, 'Gibraltar Strait
˓→':(-1.0, 1.0), 'Iceland-Faroe':(4.35,4.85),
'Indonesian Throughflow':(-15.,-13.), 'Mozambique Channel':(-25.6,-7.
˓→8), 'Pacific Equatorial Undercurrent':(24.5,28.3),
'Taiwan-Luzon Strait':(-3.0,-1.8), 'Windward Passage':(-15.,5.)}
# We need some estimated transport for the following:
# Bab_al_mandeb_Strait
# Iceland-Norway
# Hormuz Strait
Below we define a function for plotting transport time series. Note the following:
132 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
green = mean transport is within observed values
red = mean transport is not within observed values
gray = either there isn’t observed values to compare with or just a mean value is available (not a range)
[7]: def plotPanel(section,observedFlows=None,colorCode=True):
ax = plt.subplot(1,1,1)
color = '#c3c3c3'; obsLabel = None
if section.label in observedFlows.keys():
if isinstance(observedFlows[section.label],tuple):
if colorCode == True:
if min(observedFlows[section.label]) <= section.data.mean() <=
˓→max(observedFlows[section.label]):
color = '#90ee90'
else: color = '#f26161'
obsLabel = str(min(observedFlows[section.label])) + ' to ' +
˓→str(max(observedFlows[section.label]))
else: obsLabel = str(observedFlows[section.label])
plt.plot(section.time,section.data,color=color)
plt.title(section.label,fontsize=14)
plt.text(0.04,0.11,'Mean = '+'{0:.2f}'.format(section.data.mean()),transform=ax.
˓→transAxes,fontsize=14)
if obsLabel is not None: plt.text(0.04,0.04,'Obs. = '+obsLabel,transform=ax.
˓→transAxes,fontsize=14)
if section.ylim is not None: plt.ylim(section.ylim)
plt.ylabel('Transport (Sv)',fontsize=14); plt.xlabel('Time since beginning of run
˓→(yr)',fontsize=14)
return
Plot section transports in alphabetical order
Agulhas Section
[8]: agulhas = Transport(args,'agulhas_section','umo',label='Agulhas',ylim=(140,190))
plotPanel(agulhas, observedFlows=observedFlows)
1.1. Examples 133
mom6-tools Documentation, Release 0.0.post86
Bab al mandeb Strait (Red Sea)
[9]: bab = Transport(args,'Bab_al_mandeb_Strait','umo',label='Bab al mandeb Strait',ylim=(-
˓→0.5, 0.5))
plotPanel(bab, observedFlows=observedFlows)
Bering Strait
[10]: bering = Transport(args,'Bering_Strait','vmo',label='Bering Strait',ylim=(-2,3))
plotPanel(bering, observedFlows=observedFlows)
134 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
Barents opening
[11]: barents = Transport(args,'Barents_opening','vmo',label='Barents Opening',ylim=(-2,10))
plotPanel(barents, observedFlows=observedFlows)
Davis Strait
[12]: davis = Transport(args,'Davis_Strait','vmo',label='Davis Strait',ylim=(-4.0,0.5))
plotPanel(davis, observedFlows=observedFlows)
Denmark Strait
[13]: denmark = Transport(args,'Denmark_Strait','vmo',label='Denmark Strait',ylim=(-12,2))
plotPanel(denmark, observedFlows=observedFlows)
1.1. Examples 135
mom6-tools Documentation, Release 0.0.post86
Drake Passage
[14]: drake = Transport(args,'Drake_Passage','umo',label='Drake Passage',ylim=(140,190))
plotPanel(drake, observedFlows=observedFlows)
English Channel
[15]: english = Transport(args,'English_Channel','umo',label='English Channel',ylim=(-0.4,0.
˓→4))
plotPanel(english, observedFlows=observedFlows)
136 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
Florida Bahamas
[26]: florida = Transport(args,'Florida_Bahamas','vmo',label='Florida-Bahamas',ylim=(12,20))
plotPanel(florida, observedFlows=observedFlows)
Fram Strait
[17]: fram = Transport(args,'Fram_Strait','vmo',label='Fram Strait',ylim=(-10,8))
plotPanel(fram, observedFlows=observedFlows)
1.1. Examples 137
mom6-tools Documentation, Release 0.0.post86
Gibraltar Strait
[18]: gibraltar = Transport(args,'Gibraltar_Strait','umo',label='Gibraltar Strait',ylim=(-1.
˓→0,1.0))
plotPanel(gibraltar, observedFlows=observedFlows)
Hormuz Strait (Persian Gulf or Arabic Sea)
[19]: hormuz = Transport(args,'Hormuz_Strait','umo',label='Hormuz Strait',ylim=(-0.5,0.5))
plotPanel(hormuz, observedFlows=observedFlows)
138 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
Iceland Norway
[20]: iceland = Transport(args,'Iceland_Norway','vmo',label='Iceland-Norway',ylim=(-5,17))
plotPanel(iceland, observedFlows=observedFlows)
Indonesian Throughflow
[21]: indo = Transport(args,'Indonesian_Throughflow','vmo',label='Indonesian Throughflow',
˓→ylim=(-20,0))
plotPanel(indo, observedFlows=observedFlows)
1.1. Examples 139
mom6-tools Documentation, Release 0.0.post86
Mozambique Channel
[22]: mozambique = Transport(args,'Mozambique_Channel','vmo',label='Mozambique Channel',
˓→ylim=(-50,10))
plotPanel(mozambique, observedFlows=observedFlows)
Pacific undercurrent
[23]: euc = Transport(args,'Pacific_undercurrent','umo',label='Pacific Equatorial
˓→Undercurrent',ylim=None, zlim=(0,350))
plotPanel(euc, observedFlows=observedFlows)
140 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
Taiwan Luzon
[24]: taiwan = Transport(args,'Taiwan_Luzon','umo',label='Taiwan-Luzon Strait',ylim=(-15,
˓→10))
plotPanel(taiwan, observedFlows=observedFlows)
Windward Passage
[25]: windward = Transport(args,'Windward_Passage','vmo',label='Windward Passage',ylim=(-10,
˓→10))
plotPanel(windward, observedFlows=observedFlows)
1.1. Examples 141
mom6-tools Documentation, Release 0.0.post86
1.1.12 Sea ice analysis
[1]: %matplotlib inline
from mom6_tools.MOM6grid import MOM6grid
from mom6_tools.DiagsCase import DiagsCase
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
import warnings, yaml
warnings.filterwarnings("ignore")
Basemap module not found. Some regional plots may not function properly
[2]: # 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)
[3]: # Create the case instance
dcase = DiagsCase(diag_config_yml['Case'])
print('Casename is:', dcase.casename)
Casename is: g.c2b6.GJRA.TL319_t061.long_JRA_mct.076
[4]: # Load the grid
RUNDIR = dcase.get_value('RUNDIR')
grd = MOM6grid(RUNDIR+'/'+dcase.casename+'.mom6.static.nc', xrformat=False)
MOM6 grid successfully loaded...
142 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[5]: # The following parameters must be set accordingly
######################################################
year_start = '0100-01-01'
year_end = '0116-12-31'
# Put your name and email address below
author = 'Gustavo Marques (
[email protected])'
######################################################
# create an empty class object
class args:
pass
args.start_date = year_start
args.end_date = year_end
args.savefigs = False
args.time_series = True
[6]: # Create the climatology instance
cluster = NCARCluster(project='P93300612')
cluster.scale(2)
cluster
VBox(children=(HTML(value='<h2>NCARCluster</h2>'), HBox(children=(HTML(value='\n<div>
˓→\n <style scoped>\n ....
[7]: client = Client(cluster)
print(cluster.dashboard_link)
client
https://jupyterhub.ucar.edu/ch/user/gmarques/proxy/8787/status
[7]: <Client: 'tcp://10.148.10.19:46785' processes=0 threads=0, memory=0 B>
[16]: variables = ['hi', 'aice', 'time']
RUNDIR = dcase.get_value('RUNDIR')
def preprocess(ds):
'''Return the dataset with variables'''
return ds[variables]
%time ds = xr.open_mfdataset(RUNDIR+'/'+dcase.casename+'.cice.h.*.nc', \
parallel=True, chunks={'time': 12}, data_vars='minimal', \
preprocess=preprocess)
CPU times: user 1min 19s, sys: 7.99 s, total: 1min 27s
Wall time: 6min 1s
[17]: 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 0100-01-01 and 0116-12-31...
CPU times: user 7.92 ms, sys: 6.13 ms, total: 14.1 ms
Wall time: 14.5 ms
[18]: print('\n Computing time mean...')
%time ds_sel_mean = ds_sel.mean('time').compute()
1.1. Examples 143
mom6-tools Documentation, Release 0.0.post86
Computing time mean...
CPU times: user 47.9 s, sys: 1.03 s, total: 48.9 s
Wall time: 2min 39s
[19]: print('Computing monthly climatology...')
%time ds_monthly = ds.groupby("time.month").mean('time').compute()
Computing monthly climatology...
CPU times: user 1min 20s, sys: 1.72 s, total: 1min 22s
Wall time: 4min 22s
[20]: # 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')
[21]: obs_NH_mean = obs_NH.mean('time').compute()
obs_SH_mean = obs_SH.mean('time').compute()
[22]: 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
[23]: # 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)
[23]: Text(0.5, 0.98, 'ANN mean sea ice thickness, 0100-01-01 to 0116-12-31')
144 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.1. Examples 145
mom6-tools Documentation, Release 0.0.post86
JFM
[24]: 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')
(continues on next page)
146 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
plt.suptitle(suptitle)
[24]: Text(0.5, 0.98, 'JFM mean sea ice thickness, 0100-01-01 to 0116-12-31')
1.1. Examples 147
mom6-tools Documentation, Release 0.0.post86
AMJ
[25]: 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')
(continues on next page)
148 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
plt.suptitle(suptitle)
[25]: Text(0.5, 0.98, 'AMJ mean sea ice thickness, 0100-01-01 to 0116-12-31')
1.1. Examples 149
mom6-tools Documentation, Release 0.0.post86
JAS
[26]: 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')
(continues on next page)
150 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
plt.suptitle(suptitle)
[26]: Text(0.5, 0.98, 'JAS mean sea ice thickness, 0100-01-01 to 0116-12-31')
1.1. Examples 151
mom6-tools Documentation, Release 0.0.post86
OND
[27]: 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')
(continues on next page)
152 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
plt.suptitle(suptitle)
[27]: Text(0.5, 0.98, 'OND mean sea ice thickness, 0100-01-01 to 0116-12-31')
1.1. Examples 153
mom6-tools Documentation, Release 0.0.post86
[28]: (obs_SH_mean.sic * 100.).plot()
[28]: <matplotlib.collections.QuadMesh at 0x2b218a8c7ef0>
154 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
[30]: 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')
[30]: <matplotlib.contour.QuadContourSet at 0x2b218b2b42e8>
Sea ice concentration
[32]:
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')
(continues on next page)
1.1. Examples 155
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
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)
[32]: Text(0.5, 0.98, 'ANN mean ice concentration, 0100-01-01 to 0116-12-31')
156 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
Northern Hemisphere
Maximum sea ice thickness
[33]: 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)
(continues on next page)
1.1. Examples 157
mom6-tools Documentation, Release 0.0.post86
(continued from previous page)
# 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
158 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
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))
[ ]:
Reference
1.1. Examples 159
mom6-tools Documentation, Release 0.0.post86
1.2 API Reference
This page provides an auto-generated summary of mom6-tool’s API. For more details and examples, refer to the
relevant chapters in the main part of the documentation.
1.2.1 Transports across vertical sections
section_transports
1.2.2 Meridional overturning
moc
1.2.3 Poleward heat transport
poleward_heat_transport
1.2.4 Toolbox
m6toolbox A collection of useful functions. . .
1.2.5 Plotting tools
m6plot
1.3 Installing
You can install mom6-tools with pip, conda, or by installing from source.
1.3.1 Pip
Pip can be used to install mom6-tools:
pip install mom6-tools
1.3.2 Conda
To install the latest version of mom6-tools from the conda-forge repository using conda:
conda install -c conda-forge mom6-tools
160 Chapter 1. Installation (Coming Soon!)
mom6-tools Documentation, Release 0.0.post86
1.3.3 Install from Source
To install mom6-tools from source, clone the repository from github:
git clone https://github.com/NCAR/mom6-tools.git
cd mom6-tools
pip install -e .
You can also install directly from git master branch:
pip install git+https://github.com/NCAR/mom6-tools
1.3.4 Test
To run mom6-tools’s tests with pytest:
git clone https://github.com/NCAR/mom6-tools.git
cd mom6-tools
pytest - v
1.3. Installing 161
mom6-tools Documentation, Release 0.0.post86
162 Chapter 1. Installation (Coming Soon!)
CHAPTER 2
Indices and tables
• genindex
• modindex
• search
163