POP-tools Documentation Release 2021.5.28.post11+dirty

pop-tools developers

2021-09-20

USER GUIDE

1 Installation 3

2 Get in touch 5 2.1 Installing...... 5 2.2 Examples...... 6 2.3 API Reference...... 73 2.4 Contributing Guide...... 78 2.5 Changelog...... 81

Index 83

i ii POP-tools Documentation, Release 2021.5.28.post11+dirty

CI Docs Package License

USER GUIDE 1 POP-tools Documentation, Release 2021.5.28.post11+dirty

2 USER GUIDE CHAPTER ONE

INSTALLATION

pop-tools can be installed from PyPI with pip: python -m pip install pop-tools pop-tools is also available from conda-forge for conda installations: conda install -c conda-forge pop-tools

See documentation for more information.

3 POP-tools Documentation, Release 2021.5.28.post11+dirty

4 Chapter 1. Installation CHAPTER TWO

GET IN TOUCH

• If you encounter any errors or problems with pop-tools, please open an issue at the GitHub main repository. • If you have a question like “How do I compute x?”, ask on GitHub discussions. Please include a self-contained reproducible example if possible.

2.1 Installing

You can install pop-tools with pip, conda, or by installing from source.

2.1.1 Pip

Pip can be used to install pop-tools: python -m pip install pop-tools

2.1.2 Conda

To install the latest version of pop-tools from the conda-forge channel using conda: conda install -c conda-forge pop-tools

2.1.3 Install from Source

To install pop-tools from source, clone the repository from Github git clone https://github.com/NCAR/pop-tools.git cd pop-tools python -m pip install -e .

You can also install directly from git master branch:: python -m pip install git+https://github.com/NCAR/pop-tools

5 POP-tools Documentation, Release 2021.5.28.post11+dirty

2.2 Examples

2.2.1 Sample Data pop-tools provides some sample data through the pop_tools.datasets module.

Where are the sample data files?

The sample data files are downloaded automatically by pooch the first time you load them. import xarray as xr import pop_tools

To find which data files are available via pop_tools, you can run the following: pop_tools.DATASETS.registry_files

['tend_zint_100m_Fe.nc', 'iron_tracer.nc', 'daily_surface_potential_temperature.nc', 'monthly_dissolved_oxygen.nc', 'cesm_pop_monthly.T62_g17.nc', 'lateral_fill_np_array_filled_ref.npz', 'lateral_fill_np_array_tripole_filled_ref.npz', 'lateral_fill_np_array_tripole_filled_ref.20200818.npz', 'lateral_fill_np_array_filled_SOR_ref.20200820.npz', 'lateral_fill_np_array_tripole_filled_SOR_ref.20200820.npz', 'POP_gx3v7.nc', 'g.e20.G.TL319_t13.control.001_hfreq.nc', 'g.e20.G.TL319_t13.control.001_hfreq-coarsen.nc', 'Pac_POP0.1_JRA_IAF_1993-12-6-test.nc', 'Pac_grid_pbc_1301x305x62.tx01_62l.2013-07-13.nc', 'comp-grid.tx9.1v3.20170718.zarr.zip']

Once you know which file you are interested in, you can pass the name to the pop_tools.DATASETS.fetch() function. This function will download the file if it does not exist already on your local system. After the file has been downloaded, the fetch function returns the path: filepath= pop_tools.DATASETS.fetch('cesm_pop_monthly.T62_g17.nc') print(filepath)

Downloading file 'cesm_pop_monthly.T62_g17.nc' from 'ftp://ftp.cgd.ucar.edu/archive/

˓→aletheia-data/cesm-data/ocn/cesm_pop_monthly.T62_g17.nc' to '/home/docs/.pop_tools/

˓→data'.

/home/docs/.pop_tools/data/cesm_pop_monthly.T62_g17.nc

Now, we can pass the file path to the appropriate I/O package for loading the content of the file: ds= xr.open_dataset(filepath) ds

6 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

Dimensions: (time: 1, z_t: 60, nlat: 384, nlon: 320, lat_aux_grid: 395, d2: 2) Coordinates: TLAT (nlat, nlon) float64 ... TLONG (nlat, nlon) float64 ... ULAT (nlat, nlon) float64 ... ULONG (nlat, nlon) float64 ... * lat_aux_grid (lat_aux_grid) float32 -79.49 -78.95 -78.42 ... 89.47 90.0 * time (time) object 0173-01-01 00:00:00 * z_t (z_t) float32 500.0 1.5e+03 2.5e+03 ... 5.125e+05 5.375e+05 Dimensions without coordinates: nlat, nlon, d2 Data variables: SALT (time, z_t, nlat, nlon) float32 ... TEMP (time, z_t, nlat, nlon) float32 ... UVEL (time, z_t, nlat, nlon) float32 ... VVEL (time, z_t, nlat, nlon) float32 ... time_bound (time, d2) object ... Attributes: title: g.e21.G1850ECOIAF.T62_g17.004 history: Sun May 26 14:13:02 2019: ncks -4 -L 9 cesm_pop_monthl... Conventions: CF-1.0; http://www.cgd.ucar.edu/cms/eaton/netcdf/CF-cu... time_period_freq: month_1 model_doi_url: https://doi.org/10.5065/D67H1H0V contents: Diagnostic and Prognostic Variables source: CCSM POP2, the CCSM Ocean Component revision: $Id: tavg.F90 90507 2019-01-18 20:54:19Z altuntas@ucar... calendar: All years have exactly 365 days. start_time: This dataset was created on 2019-05-26 at 11:20:07.5 cell_methods: cell_methods = time: mean ==> the variable values are ... NCO: netCDF Operators version 4.7.4 (http://nco.sf.net)

%load_ext watermark %watermark - -iv -m -g -h

Compiler : GCC 9.4.0 OS : Linux Release : 5.4.0-1035-aws Machine : x86_64 Processor : x86_64 CPU cores : 2 Architecture: 64bit

Hostname: build-14766403-project-451810-pop-tools

Git hash: 4a346e950481d8efbbd525d98107e2b925ac7c91 pop_tools: 2021.5.28.post11+dirty xarray : 0.19.0

2.2. Examples 7 POP-tools Documentation, Release 2021.5.28.post11+dirty

2.2.2 Get grid

The get_grid method returns an xarray.Dataset containing grid variables for a given model grid. It relies on a checkout of binary horizontal grid and topography files from the CESM inputdata repository. The vertical grid files are in the POP2-CESM repository in the input_templates directory; they are maintained separately as part of the pop-tools repository.

%matplotlib inline import xarray as xr import pop_tools

Get a dataset for the POP_tx0.v3 tripole grid. ds= pop_tools.get_grid('POP_tx0.1v3') ds.info()

Downloading file 'inputdata/ocn/pop/tx0.1v3/grid/horiz_grid_200709.ieeer8' from

˓→'https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata/ocn/pop/tx0.1v2/grid/horiz_

˓→grid_200709.ieeer8' to '/home/docs/.pop_tools'.

/home/docs/checkouts/readthedocs.org/user_builds/pop-tools/conda/latest/lib/python3.8/

˓→site-packages/urllib3/connectionpool.py:1013: InsecureRequestWarning: Unverified

˓→HTTPS request is being made to host 'svn-ccsm-inputdata.cgd.ucar.edu'. Adding

˓→certificate verification is strongly advised. See: https://urllib3.readthedocs.io/

˓→en/1.26.x/advanced-usage.html#ssl-warnings warnings.warn(

0%| | 0.00/484M [00:00

0%| | 66.6k/484M [00:00<16:54, 477kB/s]

0%| | 481k/484M [00:00<03:27, 2.33MB/s]

0%| | 1.56M/484M [00:00<01:21, 5.89MB/s]

1%| | 4.46M/484M [00:00<00:33, 14.5MB/s]

2%| | 7.29M/484M [00:00<00:27, 17.6MB/s]

2%| | 10.1M/484M [00:00<00:22, 20.8MB/s]

3%| | 13.2M/484M [00:00<00:19, 23.9MB/s]

3%| | 16.1M/484M [00:00<00:18, 25.7MB/s]

4%| | 19.3M/484M [00:00<00:16, 27.5MB/s]

5%| | 22.1M/484M [00:01<00:17, 25.8MB/s]

5%| | 25.0M/484M [00:01<00:17, 26.7MB/s]

8 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

6%| | 27.7M/484M [00:01<00:17, 26.4MB/s]

6%| | 30.4M/484M [00:01<00:17, 26.5MB/s]

7%| | 33.5M/484M [00:01<00:17, 25.8MB/s]

8%| | 36.4M/484M [00:01<00:16, 26.8MB/s]

8%| | 39.3M/484M [00:01<00:16, 27.5MB/s]

9%| | 42.4M/484M [00:01<00:15, 28.4MB/s]

9%| | 45.2M/484M [00:01<00:16, 26.0MB/s]

10%| | 48.2M/484M [00:02<00:16, 27.1MB/s]

11%| | 51.4M/484M [00:02<00:15, 28.3MB/s]

11%| | 54.4M/484M [00:02<00:14, 29.0MB/s]

12%| | 57.3M/484M [00:02<00:15, 26.9MB/s]

12%| | 60.4M/484M [00:02<00:15, 28.1MB/s]

13%| | 63.6M/484M [00:02<00:14, 29.1MB/s]

14%| | 66.7M/484M [00:02<00:14, 29.7MB/s]

15%| | 70.2M/484M [00:02<00:14, 29.0MB/s]

15%| | 73.6M/484M [00:02<00:13, 30.4MB/s]

16%| | 77.1M/484M [00:03<00:12, 31.8MB/s]

17%| | 80.7M/484M [00:03<00:12, 32.9MB/s]

17%| | 84.0M/484M [00:03<00:12, 32.9MB/s]

18%| | 87.5M/484M [00:03<00:11, 33.5MB/s]

19%| | 90.9M/484M [00:03<00:12, 31.6MB/s]

20%| | 94.4M/484M [00:03<00:11, 32.6MB/s]

20%| | 97.9M/484M [00:03<00:11, 33.0MB/s]

21%| | 101M/484M [00:03<00:11, 33.1MB/s]

2.2. Examples 9 POP-tools Documentation, Release 2021.5.28.post11+dirty

22%| | 105M/484M [00:03<00:11, 33.6MB/s]

22%| | 108M/484M [00:03<00:11, 32.0MB/s]

23%| | 112M/484M [00:04<00:11, 32.7MB/s]

24%| | 115M/484M [00:04<00:11, 33.3MB/s]

24%| | 118M/484M [00:04<00:11, 32.9MB/s]

25%| | 122M/484M [00:04<00:10, 33.5MB/s]

26%| | 125M/484M [00:04<00:11, 32.4MB/s]

27%| | 129M/484M [00:04<00:10, 32.6MB/s]

27%| | 132M/484M [00:04<00:10, 33.2MB/s]

28%| | 136M/484M [00:04<00:10, 32.9MB/s]

29%| | 139M/484M [00:04<00:10, 33.3MB/s]

29%| | 142M/484M [00:04<00:10, 33.7MB/s]

30%| | 146M/484M [00:05<00:10, 32.7MB/s]

31%| | 149M/484M [00:05<00:10, 32.6MB/s]

32%| | 153M/484M [00:05<00:10, 32.7MB/s]

32%| | 156M/484M [00:05<00:10, 32.7MB/s]

33%| | 159M/484M [00:05<00:09, 32.9MB/s]

34%| | 163M/484M [00:05<00:09, 33.5MB/s]

34%| | 166M/484M [00:05<00:10, 30.2MB/s]

35%| | 169M/484M [00:05<00:11, 27.9MB/s]

36%| | 172M/484M [00:05<00:10, 28.6MB/s]

36%| | 175M/484M [00:06<00:10, 29.4MB/s]

37%| | 178M/484M [00:06<00:11, 27.2MB/s]

37%| | 181M/484M [00:06<00:10, 28.0MB/s]

10 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

38%| | 184M/484M [00:06<00:10, 28.4MB/s]

39%| | 187M/484M [00:06<00:10, 29.2MB/s]

39%| | 190M/484M [00:06<00:10, 27.6MB/s]

40%| | 193M/484M [00:06<00:10, 28.0MB/s]

41%| | 196M/484M [00:06<00:10, 28.7MB/s]

41%| | 199M/484M [00:06<00:10, 26.6MB/s]

42%| | 202M/484M [00:07<00:10, 27.5MB/s]

42%| | 206M/484M [00:07<00:09, 28.4MB/s]

43%| | 209M/484M [00:07<00:09, 29.1MB/s]

44%| | 212M/484M [00:07<00:09, 29.1MB/s]

44%| | 214M/484M [00:07<00:09, 27.2MB/s]

45%| | 218M/484M [00:07<00:09, 28.4MB/s]

46%| | 221M/484M [00:07<00:08, 29.3MB/s]

46%| | 224M/484M [00:07<00:09, 26.9MB/s]

47%| | 227M/484M [00:07<00:09, 28.0MB/s]

48%| | 230M/484M [00:08<00:08, 28.8MB/s]

48%| | 233M/484M [00:08<00:08, 29.7MB/s]

49%| | 236M/484M [00:08<00:08, 27.8MB/s]

49%| | 239M/484M [00:08<00:08, 28.6MB/s]

50%| | 242M/484M [00:08<00:08, 28.9MB/s]

51%| | 245M/484M [00:08<00:08, 27.3MB/s]

51%| | 248M/484M [00:08<00:08, 27.6MB/s]

52%| | 251M/484M [00:08<00:08, 28.9MB/s]

53%| | 255M/484M [00:08<00:07, 29.6MB/s]

2.2. Examples 11 POP-tools Documentation, Release 2021.5.28.post11+dirty

53%| | 258M/484M [00:08<00:07, 30.3MB/s]

54%| | 261M/484M [00:09<00:07, 28.1MB/s]

55%| | 264M/484M [00:09<00:07, 29.1MB/s]

55%| | 267M/484M [00:09<00:08, 27.1MB/s]

56%| | 270M/484M [00:09<00:07, 27.9MB/s]

56%| | 273M/484M [00:09<00:07, 28.7MB/s]

57%| | 276M/484M [00:09<00:07, 29.3MB/s]

58%| | 279M/484M [00:09<00:06, 29.8MB/s]

58%| | 282M/484M [00:09<00:07, 27.9MB/s]

59%| | 285M/484M [00:09<00:06, 28.5MB/s]

60%| | 289M/484M [00:10<00:06, 29.6MB/s]

60%| | 292M/484M [00:10<00:06, 29.8MB/s]

61%| | 295M/484M [00:10<00:06, 27.3MB/s]

62%| | 298M/484M [00:10<00:06, 28.4MB/s]

62%| | 301M/484M [00:10<00:06, 29.3MB/s]

63%| | 304M/484M [00:10<00:06, 29.8MB/s]

63%| | 307M/484M [00:10<00:06, 27.8MB/s]

64%| | 310M/484M [00:10<00:06, 28.8MB/s]

65%| | 313M/484M [00:10<00:05, 29.6MB/s]

65%| | 316M/484M [00:11<00:06, 27.2MB/s]

66%| | 319M/484M [00:11<00:05, 28.2MB/s]

67%| | 322M/484M [00:11<00:05, 29.1MB/s]

67%| | 326M/484M [00:11<00:05, 29.8MB/s]

68%| | 329M/484M [00:11<00:05, 28.2MB/s]

12 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

69%| | 332M/484M [00:11<00:05, 28.3MB/s]

69%| | 335M/484M [00:11<00:05, 29.2MB/s]

70%| | 338M/484M [00:11<00:04, 30.5MB/s]

71%| | 342M/484M [00:11<00:04, 31.6MB/s]

71%| | 345M/484M [00:11<00:04, 29.4MB/s]

72%| | 348M/484M [00:12<00:04, 30.1MB/s]

73%| | 351M/484M [00:12<00:04, 31.1MB/s]

73%| | 355M/484M [00:12<00:04, 32.1MB/s]

74%| | 358M/484M [00:12<00:04, 28.6MB/s]

75%| | 361M/484M [00:12<00:04, 26.6MB/s]

75%| | 364M/484M [00:12<00:04, 26.7MB/s]

76%| | 367M/484M [00:12<00:04, 27.3MB/s]

76%| | 369M/484M [00:12<00:04, 27.7MB/s]

77%| | 372M/484M [00:12<00:04, 25.4MB/s]

78%| | 375M/484M [00:13<00:04, 26.4MB/s]

78%| | 378M/484M [00:13<00:03, 27.3MB/s]

79%| | 381M/484M [00:13<00:03, 25.7MB/s]

79%| | 384M/484M [00:13<00:03, 26.3MB/s]

80%| | 387M/484M [00:13<00:03, 27.0MB/s]

81%| | 390M/484M [00:13<00:03, 28.0MB/s]

81%| | 393M/484M [00:13<00:03, 28.6MB/s]

82%| | 396M/484M [00:13<00:03, 26.5MB/s]

82%| | 399M/484M [00:13<00:03, 27.4MB/s]

83%| | 402M/484M [00:14<00:02, 28.5MB/s]

2.2. Examples 13 POP-tools Documentation, Release 2021.5.28.post11+dirty

84%| | 405M/484M [00:14<00:02, 27.1MB/s]

84%| | 408M/484M [00:14<00:02, 27.4MB/s]

85%| | 411M/484M [00:14<00:02, 28.4MB/s]

85%| | 414M/484M [00:14<00:02, 28.8MB/s]

86%| | 417M/484M [00:14<00:02, 29.5MB/s]

87%| | 420M/484M [00:14<00:02, 27.8MB/s]

87%| | 423M/484M [00:14<00:02, 27.8MB/s]

88%| | 426M/484M [00:14<00:02, 28.7MB/s]

89%| | 429M/484M [00:15<00:01, 29.1MB/s]

89%| | 432M/484M [00:15<00:01, 29.1MB/s]

90%| | 435M/484M [00:15<00:01, 30.4MB/s]

91%| | 438M/484M [00:15<00:01, 28.3MB/s]

91%| | 441M/484M [00:15<00:01, 29.0MB/s]

92%| | 444M/484M [00:15<00:01, 29.7MB/s]

92%| | 447M/484M [00:15<00:01, 30.4MB/s]

93%| | 450M/484M [00:15<00:01, 27.0MB/s]

94%| | 453M/484M [00:15<00:01, 24.8MB/s]

94%| | 456M/484M [00:16<00:01, 24.8MB/s]

95%| | 458M/484M [00:16<00:01, 22.7MB/s]

95%| | 461M/484M [00:16<00:01, 23.1MB/s]

96%| | 463M/484M [00:16<00:00, 23.2MB/s]

96%| | 465M/484M [00:16<00:00, 21.5MB/s]

97%| | 468M/484M [00:16<00:00, 22.0MB/s]

97%| | 470M/484M [00:16<00:00, 22.7MB/s]

14 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

98%| | 473M/484M [00:16<00:00, 23.3MB/s]

98%|| 475M/484M [00:16<00:00, 21.4MB/s]

99%|| 477M/484M [00:17<00:00, 22.0MB/s]

99%|| 480M/484M [00:17<00:00, 23.1MB/s]

100%|| 483M/484M [00:17<00:00, 22.0MB/s]

0%| | 0.00/484M [00:00

100%|| 484M/484M [00:00<00:00, 661GB/s]

Downloading file 'inputdata/ocn/pop/tx0.1v3/grid/topography_20170718.ieeei4' from

˓→'https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata/ocn/pop/tx0.1v3/grid/

˓→topography_20170718.ieeei4' to '/home/docs/.pop_tools'.

/home/docs/checkouts/readthedocs.org/user_builds/pop-tools/conda/latest/lib/python3.8/

˓→site-packages/urllib3/connectionpool.py:1013: InsecureRequestWarning: Unverified

˓→HTTPS request is being made to host 'svn-ccsm-inputdata.cgd.ucar.edu'. Adding

˓→certificate verification is strongly advised. See: https://urllib3.readthedocs.io/

˓→en/1.26.x/advanced-usage.html#ssl-warnings warnings.warn(

0%| | 0.00/34.6M [00:00

0%| | 66.6k/34.6M [00:00<01:12, 477kB/s]

2%| | 689k/34.6M [00:00<00:12, 2.79MB/s]

7%| | 2.43M/34.6M [00:00<00:03, 8.24MB/s]

14%| | 4.85M/34.6M [00:00<00:02, 13.2MB/s]

23%| | 8.04M/34.6M [00:00<00:01, 19.2MB/s]

34%| | 11.6M/34.6M [00:00<00:00, 24.5MB/s]

44%| | 15.2M/34.6M [00:00<00:00, 28.0MB/s]

53%| | 18.3M/34.6M [00:00<00:00, 28.3MB/s]

63%| | 21.8M/34.6M [00:01<00:00, 30.3MB/s]

73%| | 25.2M/34.6M [00:01<00:00, 30.3MB/s]

2.2. Examples 15 POP-tools Documentation, Release 2021.5.28.post11+dirty

83%| | 28.6M/34.6M [00:01<00:00, 31.3MB/s]

93%| | 32.2M/34.6M [00:01<00:00, 32.6MB/s]

0%| | 0.00/34.6M [00:00

100%|| 34.6M/34.6M [00:00<00:00, 36.9GB/s]

Downloading file 'inputdata/ocn/pop/tx0.1v3/grid/region_mask_20170718.ieeei4' from

˓→'https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata/ocn/pop/tx0.1v3/grid/

˓→region_mask_20170718.ieeei4' to '/home/docs/.pop_tools'.

/home/docs/checkouts/readthedocs.org/user_builds/pop-tools/conda/latest/lib/python3.8/

˓→site-packages/urllib3/connectionpool.py:1013: InsecureRequestWarning: Unverified

˓→HTTPS request is being made to host 'svn-ccsm-inputdata.cgd.ucar.edu'. Adding

˓→certificate verification is strongly advised. See: https://urllib3.readthedocs.io/

˓→en/1.26.x/advanced-usage.html#ssl-warnings warnings.warn(

0%| | 0.00/34.6M [00:00

0%| | 66.6k/34.6M [00:00<01:13, 470kB/s]

1%| | 509k/34.6M [00:00<00:16, 2.02MB/s]

6%| | 2.21M/34.6M [00:00<00:04, 7.60MB/s]

16%| | 5.39M/34.6M [00:00<00:01, 16.0MB/s]

24%| | 8.44M/34.6M [00:00<00:01, 20.8MB/s]

34%| | 11.6M/34.6M [00:00<00:00, 24.2MB/s]

44%| | 15.1M/34.6M [00:00<00:00, 25.7MB/s]

54%| | 18.5M/34.6M [00:00<00:00, 28.1MB/s]

64%| | 22.1M/34.6M [00:01<00:00, 30.4MB/s]

74%| | 25.4M/34.6M [00:01<00:00, 31.1MB/s]

83%| | 28.7M/34.6M [00:01<00:00, 31.7MB/s]

93%| | 32.3M/34.6M [00:01<00:00, 32.8MB/s]

0%| | 0.00/34.6M [00:00

16 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

100%|| 34.6M/34.6M [00:00<00:00, 34.3GB/s]

xarray.Dataset { dimensions: nlat = 2400 ; nlon = 3600 ; z_t = 62 ; z_w = 62 ; z_w_bot = 62 ; variables: float64 TLAT(nlat, nlon) ; TLAT:units = degrees_north ; TLAT:long_name = T-grid latitude ; float64 TLONG(nlat, nlon) ; TLONG:units = degrees_east ; TLONG:long_name = T-grid longitude ; float64 ULAT(nlat, nlon) ; ULAT:units = degrees_north ; ULAT:long_name = U-grid latitude ; float64 ULONG(nlat, nlon) ; ULONG:units = degrees_east ; ULONG:long_name = U-grid longitude ; float64 DXT(nlat, nlon) ; DXT:units = cm ; DXT:long_name = x-spacing centered at T points ; DXT:coordinates = TLONG TLAT ; float64 DYT(nlat, nlon) ; DYT:units = cm ; DYT:long_name = y-spacing centered at T points ; DYT:coordinates = TLONG TLAT ; float64 DXU(nlat, nlon) ; DXU:units = cm ; DXU:long_name = x-spacing centered at U points ; DXU:coordinates = ULONG ULAT ; float64 DYU(nlat, nlon) ; DYU:units = cm ; DYU:long_name = y-spacing centered at U points ; DYU:coordinates = ULONG ULAT ; float64 TAREA(nlat, nlon) ; TAREA:units = cm^2 ; TAREA:long_name = area of T cells ; TAREA:coordinates = TLONG TLAT ; float64 UAREA(nlat, nlon) ; UAREA:units = cm^2 ; UAREA:long_name = area of U cells ; UAREA:coordinates = ULONG ULAT ; int32 KMT(nlat, nlon) ; KMT:long_name = k Index of Deepest Grid Cell on T Grid ; KMT:coordinates = TLONG TLAT ; int32 REGION_MASK(nlat, nlon) ; REGION_MASK:long_name = basin index number (signed integers) ; REGION_MASK:coordinates = TLONG TLAT ; float64 z_t(z_t) ; z_t:units = cm ; (continues on next page)

2.2. Examples 17 POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) z_t:long_name = depth from surface to midpoint of layer ; z_t:positive = down ; float64 dz(z_t) ; dz:units = cm ; dz:long_name = thickness of layer k ; float64 z_w(z_w) ; z_w:units = cm ; z_w:positive = down ; z_w:long_name = depth from surface to top of layer ; float64 z_w_bot(z_w_bot) ; z_w_bot:units = cm ; z_w_bot:positive = down ; z_w_bot:long_name = depth from surface to bottom of layer ;

// global attributes: :lateral_dims = [2400, 3600] ; :vertical_dims = 62 ; :vert_grid_file = tx0.1v3_vert_grid ; :horiz_grid_fname = inputdata/ocn/pop/tx0.1v3/grid/horiz_grid_200709.ieeer8 ; :topography_fname = inputdata/ocn/pop/tx0.1v3/grid/topography_20170718.ieeei4

˓→; :region_mask_fname = inputdata/ocn/pop/tx0.1v3/grid/region_mask_20170718.

˓→ieeei4 ; :type = tripole ; :title = POP_tx0.1v3 grid ; }

Visualize grid

Take a quick look at KMT (k Index of Deepest Grid Cell on T Grid), applying a land-mask criterion along the way. h= ds.KMT.where(ds.KMT>0).plot()

18 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

And the coordinates: TLAT h= ds.TLAT.where(ds.KMT>0).plot()

and TLONG h= ds.TLONG.where(ds.KMT>0).plot()

2.2. Examples 19 POP-tools Documentation, Release 2021.5.28.post11+dirty

SCRIP format

It is also possible to get the grid file in SCRIP format which is useful for regridding applications with ESMF. ds= pop_tools.get_grid('POP_tx0.1v3', scrip= True) ds.info() xarray.Dataset { dimensions: grid_rank = 2 ; grid_size = 8640000 ; grid_corners = 4 ; variables: int32 grid_dims(grid_rank) ; float64 grid_center_lat(grid_size) ; grid_center_lat:units = degrees ; float64 grid_center_lon(grid_size) ; grid_center_lon:units = degrees ; float64 grid_corner_lat(grid_size, grid_corners) ; grid_corner_lat:units = degrees ; float64 grid_corner_lon(grid_size, grid_corners) ; grid_corner_lon:units = degrees ; int64 grid_imask(grid_size) ; grid_imask:units = unitless ;

// global attributes: :lateral_dims = [2400, 3600] ; :vertical_dims = 62 ; :vert_grid_file = tx0.1v3_vert_grid ; :horiz_grid_fname = inputdata/ocn/pop/tx0.1v3/grid/horiz_grid_200709.ieeer8 ; :topography_fname = inputdata/ocn/pop/tx0.1v3/grid/topography_20170718.ieeei4

˓→; (continues on next page)

20 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) :region_mask_fname = inputdata/ocn/pop/tx0.1v3/grid/region_mask_20170718.

˓→ieeei4 ; :type = tripole ; :title = POP_tx0.1v3 grid ; :conventions = SCRIP ; }

%load_ext watermark %watermark -d -iv -m -g

Compiler : GCC 9.4.0 OS : Linux Release : 5.4.0-1035-aws Machine : x86_64 Processor : x86_64 CPU cores : 2 Architecture: 64bit

Git hash: 4a346e950481d8efbbd525d98107e2b925ac7c91 xarray : 0.19.0 pop_tools: 2021.5.28.post11+dirty

2.2.3 Equation of state pop_tools.eos implements the model’s equation of state.

%matplotlib inline import xarray as xr import pop_tools

Show check value

McDougall, T.J., D.R. Jackett, D.G. Wright, and R. Feistel, 2003: Accurate and Computationally Efficient Algorithms for Potential Temperature and Density of Seawater. J. Atmos. Oceanic Technol., 20, 730–741, doi:10.1175/1520- 0426(2003)20<730:AACEAF>2.0.CO;2. test value: • 푟ℎ표 = 1033.213387푘푔/푚3; • 푆 = 35.0 PSU, 푡ℎ푒푡푎 = 20.0 C, 푝푟푒푠푠푢푟푒 = 2000.0 dbars pop_tools.eos(salt=35.0, temp=20.0, pressure=2000.0)

1033.2133865866824

2.2. Examples 21 POP-tools Documentation, Release 2021.5.28.post11+dirty

Load POP dataset using dask filepath= pop_tools.DATASETS.fetch("cesm_pop_monthly.T62_g17.nc") ds= xr.open_dataset(filepath, decode_times= False, decode_coords=False, chunks={'z_t

˓→': 20}) ds

Dimensions: (time: 1, z_t: 60, nlat: 384, nlon: 320, lat_aux_grid: 395, d2: 2) Coordinates: * lat_aux_grid (lat_aux_grid) float32 -79.49 -78.95 -78.42 ... 89.47 90.0 * time (time) float64 6.314e+04 * z_t (z_t) float32 500.0 1.5e+03 2.5e+03 ... 5.125e+05 5.375e+05 Dimensions without coordinates: nlat, nlon, d2 Data variables: SALT (time, z_t, nlat, nlon) float32 dask.array

˓→320), meta=np.ndarray> TEMP (time, z_t, nlat, nlon) float32 dask.array

˓→320), meta=np.ndarray> TLAT (nlat, nlon) float64 dask.array

˓→ndarray> TLONG (nlat, nlon) float64 dask.array

˓→ndarray> ULAT (nlat, nlon) float64 dask.array

˓→ndarray> ULONG (nlat, nlon) float64 dask.array

˓→ndarray> UVEL (time, z_t, nlat, nlon) float32 dask.array

˓→320), meta=np.ndarray> VVEL (time, z_t, nlat, nlon) float32 dask.array

˓→320), meta=np.ndarray> time_bound (time, d2) float64 dask.array Attributes: title: g.e21.G1850ECOIAF.T62_g17.004 history: Sun May 26 14:13:02 2019: ncks -4 -L 9 cesm_pop_monthl... Conventions: CF-1.0; http://www.cgd.ucar.edu/cms/eaton/netcdf/CF-cu... time_period_freq: month_1 model_doi_url: https://doi.org/10.5065/D67H1H0V contents: Diagnostic and Prognostic Variables source: CCSM POP2, the CCSM Ocean Component revision: $Id: tavg.F90 90507 2019-01-18 20:54:19Z altuntas@ucar... calendar: All years have exactly 365 days. start_time: This dataset was created on 2019-05-26 at 11:20:07.5 cell_methods: cell_methods = time: mean ==> the variable values are ... NCO: netCDF Operators version 4.7.4 (http://nco.sf.net)

22 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

Compute in situ density

%%time rho= pop_tools.eos(ds.SALT, ds.TEMP, depth=ds.z_t * 1e-2)

CPU times: user 46.7 ms, sys: 7.22 ms, total: 53.9 ms Wall time: 53.6 ms

Visualize density field h= rho.isel(time=0, z_t=0).plot()

h= rho.isel(time=0, nlon=200).plot(yincrease= False)

2.2. Examples 23 POP-tools Documentation, Release 2021.5.28.post11+dirty

%load_ext watermark %watermark -d -iv -m -g -h

Compiler : GCC 9.4.0 OS : Linux Release : 5.4.0-1035-aws Machine : x86_64 Processor : x86_64 CPU cores : 2 Architecture: 64bit

Hostname: build-14766403-project-451810-pop-tools

Git hash: 4a346e950481d8efbbd525d98107e2b925ac7c91 xarray : 0.19.0 pop_tools: 2021.5.28.post11+dirty

24 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

2.2.4 Region masks

POP includes a default region mask as a component of the grid information. This is often not super relevant for analyses. pop_tools provides several alternative region masks; these are demostrated here.

Import packages

%matplotlib inline import matplotlib.colors as colors import matplotlib.pyplot as plt import numpy as np import xarray as xr import pop_tools

Load POP grid as xarray.Dataset grid_name='POP_gx1v7' ds= pop_tools.get_grid(grid_name) ds

Downloading file 'inputdata/ocn/pop/gx1v7/grid/horiz_grid_20010402.ieeer8' from

˓→'https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata/ocn/pop/gx1v7/grid/horiz_

˓→grid_20010402.ieeer8' to '/home/docs/.pop_tools'.

/home/docs/checkouts/readthedocs.org/user_builds/pop-tools/conda/latest/lib/python3.8/

˓→site-packages/urllib3/connectionpool.py:1013: InsecureRequestWarning: Unverified

˓→HTTPS request is being made to host 'svn-ccsm-inputdata.cgd.ucar.edu'. Adding

˓→certificate verification is strongly advised. See: https://urllib3.readthedocs.io/

˓→en/1.26.x/advanced-usage.html#ssl-warnings warnings.warn(

0%| | 0.00/6.88M [00:00

1%| | 66.6k/6.88M [00:00<00:14, 477kB/s]

6%| | 443k/6.88M [00:00<00:03, 1.76MB/s]

29%| | 2.00M/6.88M [00:00<00:00, 6.90MB/s]

74%| | 5.10M/6.88M [00:00<00:00, 15.3MB/s]

0%| | 0.00/6.88M [00:00

100%|| 6.88M/6.88M [00:00<00:00, 7.59GB/s]

2.2. Examples 25 POP-tools Documentation, Release 2021.5.28.post11+dirty

Downloading file 'inputdata/ocn/pop/gx1v7/grid/topography_20161215.ieeei4' from

˓→'https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata/ocn/pop/gx1v7/grid/

˓→topography_20161215.ieeei4' to '/home/docs/.pop_tools'.

/home/docs/checkouts/readthedocs.org/user_builds/pop-tools/conda/latest/lib/python3.8/

˓→site-packages/urllib3/connectionpool.py:1013: InsecureRequestWarning: Unverified

˓→HTTPS request is being made to host 'svn-ccsm-inputdata.cgd.ucar.edu'. Adding

˓→certificate verification is strongly advised. See: https://urllib3.readthedocs.io/

˓→en/1.26.x/advanced-usage.html#ssl-warnings warnings.warn(

0%| | 0.00/492k [00:00

20%| | 99.3k/492k [00:00<00:00, 707kB/s]

0%| | 0.00/492k [00:00

100%|| 492k/492k [00:00<00:00, 483MB/s]

Downloading file 'inputdata/ocn/pop/gx1v7/grid/region_mask_20151008.ieeei4' from

˓→'https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata/ocn/pop/gx1v7/grid/region_

˓→mask_20151008.ieeei4' to '/home/docs/.pop_tools'.

/home/docs/checkouts/readthedocs.org/user_builds/pop-tools/conda/latest/lib/python3.8/

˓→site-packages/urllib3/connectionpool.py:1013: InsecureRequestWarning: Unverified

˓→HTTPS request is being made to host 'svn-ccsm-inputdata.cgd.ucar.edu'. Adding

˓→certificate verification is strongly advised. See: https://urllib3.readthedocs.io/

˓→en/1.26.x/advanced-usage.html#ssl-warnings warnings.warn(

0%| | 0.00/492k [00:00

14%| | 66.6k/492k [00:00<00:00, 471kB/s]

0%| | 0.00/492k [00:00

100%|| 492k/492k [00:00<00:00, 490MB/s]

Dimensions: (nlat: 384, nlon: 320, z_t: 60, z_w: 60, z_w_bot: 60, nreg: 13) Coordinates: * z_t (z_t) float64 500.0 1.5e+03 2.5e+03 ... 5.125e+05 5.375e+05 * z_w (z_w) float64 0.0 1e+03 2e+03 3e+03 ... 4.75e+05 5e+05 5.25e+05 * z_w_bot (z_w_bot) float64 1e+03 2e+03 3e+03 ... 5e+05 5.25e+05 5.5e+05 * nreg (nreg) int64 0 1 2 3 4 5 6 7 8 9 10 11 12 Dimensions without coordinates: nlat, nlon Data variables: (12/15) TLAT (nlat, nlon) float64 -79.22 -79.22 -79.22 ... 72.2 72.19 72.19 TLONG (nlat, nlon) float64 320.6 321.7 322.8 ... 318.9 319.4 319.8 ULAT (nlat, nlon) float64 -78.95 -78.95 -78.95 ... 72.42 72.41 72.41 (continues on next page)

26 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) ULONG (nlat, nlon) float64 321.1 322.3 323.4 ... 319.2 319.6 320.0 DXT (nlat, nlon) float64 1.894e+06 1.893e+06 ... 1.473e+06 DYT (nlat, nlon) float64 5.94e+06 5.94e+06 ... 5.046e+06 5.046e+06 ...... UAREA (nlat, nlon) float64 1.423e+13 1.423e+13 ... 7.639e+12 KMT (nlat, nlon) int32 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0 REGION_MASK (nlat, nlon) int32 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0 dz (z_t) float64 1e+03 1e+03 1e+03 ... 2.499e+04 2.5e+04 2.5e+04 region_name (nreg)

Plot default REGION_MASK

The default REGION_MASK is a 2-D array with unique integer values for each region. Negative integers denote “marginal seas,” which are not directly connected to the ocean. regions= np.array(np.unique(ds.REGION_MASK)) regions array([-13, -12, -5, 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11], dtype=int32) ds.REGION_MASK.plot.contourf(levels=regions, cmap='tab20');

2.2. Examples 27 POP-tools Documentation, Release 2021.5.28.post11+dirty

More useful region masks

It’s often more useful to define a region mask as a 3-D array of zeros and ones, where the first dimension is region; this permits overlapping regions and is convenient for computation because the mask can be applied by multiplication, which yields a region dimension via broadcasting. pop_tools supports converting the default REGION_MASK to this type of mask thru the region_mask_3d func- tion. mask3d= pop_tools.region_mask_3d(grid_name, mask_name='default') mask3d

array([[[0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], ..., [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]],

[[0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], ..., [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]],

[[0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], (continues on next page)

28 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) [0., 0., 0., ..., 0., 0., 0.], ..., ...... , [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]],

[[0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], ..., [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]],

[[0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], ..., [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]]]) Coordinates: * region (region)

This mask includes a coordinate variable with the region names. mask3d.region

array(['Black Sea', 'Baltic Sea', 'Red Sea', 'Southern Ocean', 'Pacific Ocean', 'Indian Ocean', 'Persian Gulf', 'Atlantic Ocean', 'Mediterranean Sea', 'Lab. Sea & Baffin Bay', 'GIN Seas', 'Arctic Ocean', 'Hudson Bay'], dtype='

A particular region can be selected by name. mask3d.sel(region='Southern Ocean').plot();

2.2. Examples 29 POP-tools Documentation, Release 2021.5.28.post11+dirty

To visualize all the regions, we can define a help plotting function, def visualize_mask(mask3d): nregion= len(mask3d.region)

# mask out land mask3d= mask3d.where(ds.KMT>0)

# visualize the regions ncol= int(np.sqrt(nregion)) nrow= int(nregion/ ncol)+ min(1, nregion% ncol)

fig, ax= plt.subplots(nrow, ncol, figsize=(4 * ncol,3 * nrow), constrained_ ˓→layout=True)

for i, region in enumerate(mask3d.region.values): plt.axes(ax.ravel()[i]) mask3d.sel(region=region).plot()

# delete the unused axes for i in range(nregion, ncol * nrow): fig.delaxes(ax.ravel()[i])

fig.suptitle(f'Mask name = {mask3d.mask_name}', fontsize=16) and apply it to the default mask created above. visualize_mask(mask3d)

30 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

2.2. Examples 31 POP-tools Documentation, Release 2021.5.28.post11+dirty

Alternative region masks

Other useful region masks are pre-defined in the package. list_region_masks returns a list of pre-defined masks. region_masks= pop_tools.list_region_masks(grid_name) region_masks

['lat-range-basin', 'Pacific-Indian-Atlantic']

We can visualize all of these using the helper function above. for region_mask in region_masks: mask3d= pop_tools.region_mask_3d(grid_name, mask_name=region_mask) visualize_mask(mask3d)

32 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

2.2. Examples 33 POP-tools Documentation, Release 2021.5.28.post11+dirty

To illustrated how regions cover the global domain, including with overlap, we can sum over the region dimension. mask3d= pop_tools.region_mask_3d(grid_name, mask_name='lat-range-basin') mask3d.sum('region').plot();

34 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

User defined region masks

Finally, it is also possible to make a region mask on the fly by building a dictionary containing the defining logic. region_mask_3d accepts a region_defs argument. This is a dictionary of the following form. region_defs= {region1_name: list_of_criteria_dicts_1, region2_name: list_of_criteria_dicts_2,...}

The list_of_criteria_dicts are lists of dictionaries; each must include the keys ‘match’ or ‘bounds’. For instance: list_of_criteria_dicts_1=[{'match':{'REGION_MASK':[1,2,3,6]}, 'bounds':{'TLAT':[-90.,-30.]}}] will return a mask where the default REGION_MASK matches the specified values and TLAT falls between the speci- fied bounds. Multiple entries in the list_of_criteria_dicts are applied with an “or” condition. Here’s an example region mask generated for the North Atlantic Subpolar and Subtropical Gyres. region_defs={ 'NAtl-STG':[ {'match':{'REGION_MASK':[6]},'bounds':{'TLAT':[32.0, 42.0],'TLONG':

˓→[310.0, 350.0]}} ], 'NAtl-SPG':[ {'match':{'REGION_MASK':[6]},'bounds':{'TLAT':[50.0, 60.0],'TLONG':

˓→[310.0, 350.0]}} ], }

(continues on next page)

2.2. Examples 35 POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) mask3d= pop_tools.region_mask_3d(grid_name, region_defs=region_defs, mask_name='N.

˓→Atlantic Gyres') visualize_mask(mask3d)

%load_ext watermark %watermark -d -iv -m -g -h

Compiler : GCC 9.4.0 OS : Linux Release : 5.4.0-1035-aws Machine : x86_64 Processor : x86_64 CPU cores : 2 Architecture: 64bit

(continues on next page)

36 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) Hostname: build-14766403-project-451810-pop-tools

Git hash: 4a346e950481d8efbbd525d98107e2b925ac7c91 numpy : 1.20.3 pop_tools : 2021.5.28.post11+dirty xarray : 0.19.0 matplotlib: 3.4.3

2.2.5 Lateral fill concept

When regidding datasets for initial conditions, it is necessary to ensure that all model points have data. In many cases, differences between land-sea masks yield regions along the margins that require filling. The lateral_fill_np_array() routine applies an iterative filling procedure to accomplish this. This is illustrated here.

Import packages

%matplotlib inline import matplotlib.pyplot as plt import numpy as np import xarray as xr import pop_tools

Generate some psuedo-data with coastline dx, dy= 0.05, 0.05 y, x= np.mgrid[slice(1- dy,3+ dy, dy), slice(1- dx,5+ dx, dx)] z_orig= np.sin(x) ** 10+ np.cos(10+y * x) * np.cos(x) valid_points= np.ones(z_orig.shape, dtype=np.bool) valid_points= np.where(y< 0.5 * np.sin(5 * x)+ 1.5, False, valid_points) z_orig= np.where(~valid_points, np.nan, z_orig) z_orig[0, :]= np.nan cb= plt.pcolormesh(z_orig, vmin=-1, vmax=2.0) h= plt.colorbar(cb)

/tmp/ipykernel_2739/4059193687.py:7: DeprecationWarning: `np.bool` is a deprecated

˓→alias for the builtin `bool`. To silence this warning, use `bool` by itself. Doing

˓→this will not modify any behavior and is safe. If you specifically wanted the numpy

˓→scalar type, use `np.bool_` here. Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/

˓→release/1.20.0-notes.html#deprecations valid_points = np.ones(z_orig.shape, dtype=np.bool)

2.2. Examples 37 POP-tools Documentation, Release 2021.5.28.post11+dirty

Add missing values in one embayment and a random block in the top of the domain. Put some “blobs” of elevated values to show periodicity. z_miss= z_orig.copy() z_miss[:20, 62:]= np.nan z_miss[35:, 55:70]= np.nan z_miss[15:18,0:2]= 10.0 z_miss[-2:, 12:20]= 10.0 cb= plt.pcolormesh(z_miss, vmin=-1, vmax=2.0) h= plt.colorbar(cb)

38 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

Perform lateral fill

%%time z_fill= pop_tools.lateral_fill_np_array(z_miss, valid_points, ltripole= False) plt.figure() cb= plt.pcolormesh(z_fill, vmin=-1, vmax=2.0) h= plt.colorbar(cb)

CPU times: user 1e+03 ms, sys: 4.16 ms, total: 1 s Wall time: 935 ms

2.2. Examples 39 POP-tools Documentation, Release 2021.5.28.post11+dirty

Setting ltripole = True makes the domain periodic across the top boundary.

%%time z_fill= pop_tools.lateral_fill_np_array(z_miss, valid_points, ltripole= True) plt.figure() cb= plt.pcolormesh(z_fill, vmin=-1, vmax=2.0) h= plt.colorbar(cb)

CPU times: user 172 ms, sys: 0 ns, total: 172 ms Wall time: 101 ms

40 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

%load_ext watermark %watermark -d -iv -m -g -h

Compiler : GCC 9.4.0 OS : Linux Release : 5.4.0-1035-aws Machine : x86_64 Processor : x86_64 CPU cores : 2 Architecture: 64bit

Hostname: build-14766403-project-451810-pop-tools

Git hash: 4a346e950481d8efbbd525d98107e2b925ac7c91 matplotlib: 3.4.3 numpy : 1.20.3 xarray : 0.19.0 pop_tools : 2021.5.28.post11+dirty

2.2.6 Lateral fill on model grid

This example shows how to apply lateral_fill() on a model dataset. We use a model grid dataset for illustration purposes.

Import packages

%matplotlib inline import numpy as np import xarray as xr import pop_tools ds= pop_tools.get_grid('POP_gx3v7') ds

Downloading file 'inputdata/ocn/pop/gx3v7/grid/horiz_grid_20030806.ieeer8' from

˓→'https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata/ocn/pop/gx3v7/grid/horiz_

˓→grid_20030806.ieeer8' to '/home/docs/.pop_tools'.

/home/docs/checkouts/readthedocs.org/user_builds/pop-tools/conda/latest/lib/python3.8/

˓→site-packages/urllib3/connectionpool.py:1013: InsecureRequestWarning: Unverified

˓→HTTPS request is being made to host 'svn-ccsm-inputdata.cgd.ucar.edu'. Adding

˓→certificate verification is strongly advised. See: https://urllib3.readthedocs.io/

˓→en/1.26.x/advanced-usage.html#ssl-warnings warnings.warn(

0%| | 0.00/650k [00:00

10%| | 66.6k/650k [00:00<00:01, 488kB/s]

2.2. Examples 41 POP-tools Documentation, Release 2021.5.28.post11+dirty

88%| | 574k/650k [00:00<00:00, 2.84MB/s]

0%| | 0.00/650k [00:00

100%|| 650k/650k [00:00<00:00, 862MB/s]

Downloading file 'inputdata/ocn/pop/gx3v7/grid/topography_20100105.ieeei4' from

˓→'https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata/ocn/pop/gx3v7/grid/

˓→topography_20100105.ieeei4' to '/home/docs/.pop_tools'.

/home/docs/checkouts/readthedocs.org/user_builds/pop-tools/conda/latest/lib/python3.8/

˓→site-packages/urllib3/connectionpool.py:1013: InsecureRequestWarning: Unverified

˓→HTTPS request is being made to host 'svn-ccsm-inputdata.cgd.ucar.edu'. Adding

˓→certificate verification is strongly advised. See: https://urllib3.readthedocs.io/

˓→en/1.26.x/advanced-usage.html#ssl-warnings warnings.warn(

0%| | 0.00/46.4k [00:00

0%| | 0.00/46.4k [00:00

100%|| 46.4k/46.4k [00:00<00:00, 48.6MB/s]

Downloading file 'inputdata/ocn/pop/gx3v7/grid/region_mask_20090831.ieeei4' from

˓→'https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata/ocn/pop/gx3v7/grid/region_

˓→mask_20090831.ieeei4' to '/home/docs/.pop_tools'.

/home/docs/checkouts/readthedocs.org/user_builds/pop-tools/conda/latest/lib/python3.8/

˓→site-packages/urllib3/connectionpool.py:1013: InsecureRequestWarning: Unverified

˓→HTTPS request is being made to host 'svn-ccsm-inputdata.cgd.ucar.edu'. Adding

˓→certificate verification is strongly advised. See: https://urllib3.readthedocs.io/

˓→en/1.26.x/advanced-usage.html#ssl-warnings warnings.warn(

0%| | 0.00/46.4k [00:00

0%| | 0.00/46.4k [00:00

100%|| 46.4k/46.4k [00:00<00:00, 48.5MB/s]

Dimensions: (nlat: 116, nlon: 100, z_t: 60, z_w: 60, z_w_bot: 60) Coordinates: * z_t (z_t) float64 500.0 1.5e+03 2.5e+03 ... 5.125e+05 5.375e+05 * z_w (z_w) float64 0.0 1e+03 2e+03 3e+03 ... 4.75e+05 5e+05 5.25e+05 * z_w_bot (z_w_bot) float64 1e+03 2e+03 3e+03 ... 5e+05 5.25e+05 5.5e+05 Dimensions without coordinates: nlat, nlon (continues on next page)

42 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) Data variables: (12/13) TLAT (nlat, nlon) float64 -79.5 -79.5 -79.5 ... 68.36 68.26 68.21 TLONG (nlat, nlon) float64 323.3 326.9 330.5 ... 317.8 319.3 320.8 ULAT (nlat, nlon) float64 -78.73 -78.73 -78.73 ... 68.49 68.42 68.4 ULONG (nlat, nlon) float64 325.1 328.7 332.3 ... 318.7 320.1 321.5 DXT (nlat, nlon) float64 6.842e+06 6.828e+06 ... 6.129e+06 DYT (nlat, nlon) float64 1.686e+07 1.686e+07 ... 4.524e+06 ...... DYU (nlat, nlon) float64 1.686e+07 1.686e+07 ... 1.069e+07 TAREA (nlat, nlon) float64 1.154e+14 1.151e+14 ... 2.773e+13 UAREA (nlat, nlon) float64 1.318e+14 1.318e+14 ... 6.256e+13 6.27e+13 KMT (nlat, nlon) int32 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0 REGION_MASK (nlat, nlon) int32 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0 dz (z_t) float64 1e+03 1e+03 1e+03 ... 2.499e+04 2.5e+04 2.5e+04 Attributes: lateral_dims: [116, 100] vertical_dims: 60 vert_grid_file: gx3v7_vert_grid horiz_grid_fname: inputdata/ocn/pop/gx3v7/grid/horiz_grid_20030806.ieeer8 topography_fname: inputdata/ocn/pop/gx3v7/grid/topography_20100105.ieeei4 region_mask_fname: inputdata/ocn/pop/gx3v7/grid/region_mask_20090831.ieeei4 type: dipole title: POP_gx3v7 grid

Generate a field with some missing values field= ds.KMT.copy() * 1.0 field= field.where(ds.KMT>0) field.values[20:40, :]= np.nan field.plot()

2.2. Examples 43 POP-tools Documentation, Release 2021.5.28.post11+dirty

Fill the missing values field_filled= pop_tools.lateral_fill(field, isvalid_mask=(ds.KMT>0)) h= field_filled.plot()

44 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

%load_ext watermark %watermark -d -iv -m -g -h

Compiler : GCC 9.4.0 OS : Linux Release : 5.4.0-1035-aws Machine : x86_64 Processor : x86_64 CPU cores : 2 Architecture: 64bit

Hostname: build-14766403-project-451810-pop-tools

Git hash: 4a346e950481d8efbbd525d98107e2b925ac7c91

pop_tools: 2021.5.28.post11+dirty numpy : 1.20.3 xarray : 0.19.0

2.2.7 Using xgcm with POP output

In this notebook we will use xgcm capability to calculate divergence, vorticity and scalar gradients from high resolution (0.1∘) POP output. We will 1. demonstrate the functions needed for these operations with basic xarray 2. translate them to the corresponding xgcm version using diff() and interp(). 3. use xgcm.get_metric capabilities to simplify the code. The metrics functionality lets us write generalized div, grad and curl functions that should be available in xgcm in the future (see xgcm/xgcm #187). This notebook was contributed by Anna-Lena Deppenmeier.

Import packages

import numpy as np import xarray as xr import xgcm from matplotlib import pyplot as plt

import pop_tools

%matplotlib inline plt.rcParams["figure.figsize"]=(10,6)

2.2. Examples 45 POP-tools Documentation, Release 2021.5.28.post11+dirty

Open example dataset and modify it to work with xgcm

For the relabeling the dataset must contain DZU and DZT (they are also needed in calculations later on)

# open sample data filepath= pop_tools.DATASETS.fetch('Pac_POP0.1_JRA_IAF_1993-12-6-test.nc') ds= xr.open_dataset(filepath)

# get DZU and DZT, needed for operations later on filepath_g= pop_tools.DATASETS.fetch('Pac_grid_pbc_1301x305x62.tx01_62l.2013-07-13.nc

˓→') ds_g= xr.open_dataset(filepath_g) ds["DZT"]= ds_g.DZT ds["DZU"]= ds_g.DZU ds["cell_volume_t"]= ds_g.DZT * ds_g.DXT * ds_g.DYT ds["cell_volume_u"]= ds_g.DZU * ds_g.DXT * ds_g.DYT ds contains the usual dimensions nlat, nlon, etc: ds

Dimensions: (nlat: 305, nlon: 1301, time: 1, z_t: 62, z_w: 62, z_w_bot: 62, z_

˓→w_top: 62) Coordinates: * time (time) object 0036-12-07 00:00:00 * z_t (z_t) float32 500.0 1.5e+03 2.5e+03 ... 5.625e+05 5.875e+05 * z_w (z_w) float32 0.0 1e+03 2e+03 ... 5.25e+05 5.5e+05 5.75e+05 * z_w_top (z_w_top) float32 0.0 1e+03 2e+03 ... 5.5e+05 5.75e+05 * z_w_bot (z_w_bot) float32 1e+03 2e+03 3e+03 ... 5.75e+05 6e+05 ULONG (nlat, nlon) float64 ... ULAT (nlat, nlon) float64 ... TLONG (nlat, nlon) float64 ... TLAT (nlat, nlon) float64 ... Dimensions without coordinates: nlat, nlon Data variables: (12/30) TEND_TEMP (time, z_t, nlat, nlon) float32 ... UET (time, z_t, nlat, nlon) float32 ... VNT (time, z_t, nlat, nlon) float32 ... WTT (time, z_w_top, nlat, nlon) float32 ... KPP_SRC_TEMP (time, z_t, nlat, nlon) float32 ... UVEL (time, z_t, nlat, nlon) float32 ...... SHF (time, nlat, nlon) float32 ... SHF_QSW (time, nlat, nlon) float32 ... DZT (z_t, nlat, nlon) float32 ... DZU (z_t, nlat, nlon) float32 ... cell_volume_t (z_t, nlat, nlon) float64 1.153e+15 1.153e+15 ... 2.884e+16 cell_volume_u (z_t, nlat, nlon) float64 1.153e+15 1.153e+15 ... 2.884e+16 Attributes: title: g.e20.G.TL319_t13.control.001_hfreq history: none Conventions: CF-1.0; http://www.cgd.ucar.edu/cms/eaton/netcdf/CF-cu... time_period_freq: day_5 model_doi_url: https://doi.org/10.5065/D67H1H0V contents: Diagnostic and Prognostic Variables (continues on next page)

46 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) source: CCSM POP2, the CCSM Ocean Component revision: $Id: tavg.F90 89091 2018-04-30 15:58:32Z altuntas@ucar... calendar: All years have exactly 365 days. start_time: This dataset was created on 2018-12-14 at 16:05:58.8 cell_methods: cell_methods = time: mean ==> the variable values are ...

We call to_xgcm_grid_dataset() to make the POP dataset xgcm compatible. This means that the dimensions need to be renamed so that xgcm knows which variables are at T-points and which are at U-points. grid, ds_ren= pop_tools.to_xgcm_grid_dataset(ds, periodic= False) ds_ren contains all variables from ds, but nlat/nlon have been replaced by nlat_t/nlon_t and nlat_u/ nlon_u depending on which points the variables are at: ds_ren

Dimensions: (nlat: 305, nlat_t: 305, nlat_u: 305, nlon: 1301, nlon_t: 1301,

˓→nlon_u: 1301, time: 1, z_t: 62, z_w_bot: 62, z_w_top: 62) Coordinates: * time (time) object 0036-12-07 00:00:00 * z_t (z_t) float32 500.0 1.5e+03 2.5e+03 ... 5.625e+05 5.875e+05 * z_w_top (z_w_top) float32 0.0 1e+03 2e+03 ... 5.5e+05 5.75e+05 * z_w_bot (z_w_bot) float32 1e+03 2e+03 3e+03 ... 5.75e+05 6e+05 ULONG (nlat_u, nlon_u) float64 160.0 160.1 160.2 ... -70.1 -70.0 ULAT (nlat_u, nlon_u) float64 -15.03 -15.03 ... 15.03 15.03 TLONG (nlat_t, nlon_t) float64 159.9 160.0 160.1 ... 289.9 290.0 TLAT (nlat_t, nlon_t) float64 -15.07 -15.07 ... 14.98 14.98 * nlon_u (nlon_u) int64 1 2 3 4 5 6 ... 1296 1297 1298 1299 1300 1301 * nlat_u (nlat_u) int64 1 2 3 4 5 6 7 ... 299 300 301 302 303 304 305 * nlon_t (nlon_t) float64 0.5 1.5 2.5 ... 1.298e+03 1.3e+03 1.3e+03 * nlat_t (nlat_t) float64 0.5 1.5 2.5 3.5 ... 301.5 302.5 303.5 304.5 Dimensions without coordinates: nlat, nlon Data variables: (12/30) TEND_TEMP (time, z_t, nlat_t, nlon_t) float32 3.461e-08 ... nan UET (time, z_t, nlat_t, nlon_u) float32 -0.0005898 ... 0.0 VNT (time, z_t, nlat_u, nlon_t) float32 0.0002135 ... 0.0 WTT (time, z_w_top, nlat_t, nlon_t) float32 0.0 0.0 ... nan nan KPP_SRC_TEMP (time, z_t, nlat_t, nlon_t) float32 1.908e-06 ... nan UVEL (time, z_t, nlat_u, nlon_u) float32 -23.85 -25.17 ... nan ...... SHF (time, nlat_t, nlon_t) float32 94.64 96.18 ... -58.45 -58.65 SHF_QSW (time, nlat_t, nlon_t) float32 245.0 245.2 ... 204.0 203.9 DZT (z_t, nlat_t, nlon_t) float32 1e+03 1e+03 ... 2.5e+04 DZU (z_t, nlat_u, nlon_u) float32 1e+03 1e+03 ... 2.5e+04 cell_volume_t (z_t, nlat, nlon) float64 1.153e+15 1.153e+15 ... 2.884e+16 cell_volume_u (z_t, nlat, nlon) float64 1.153e+15 1.153e+15 ... 2.884e+16 Attributes: title: g.e20.G.TL319_t13.control.001_hfreq history: none Conventions: CF-1.0; http://www.cgd.ucar.edu/cms/eaton/netcdf/CF-cu... time_period_freq: day_5 model_doi_url: https://doi.org/10.5065/D67H1H0V contents: Diagnostic and Prognostic Variables source: CCSM POP2, the CCSM Ocean Component revision: $Id: tavg.F90 89091 2018-04-30 15:58:32Z altuntas@ucar... (continues on next page)

2.2. Examples 47 POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) calendar: All years have exactly 365 days. start_time: This dataset was created on 2018-12-14 at 16:05:58.8 cell_methods: cell_methods = time: mean ==> the variable values are ... to_xgcm_grid_dataset() also created an xgcm.Grid object named grid. This object will make it easy to do grid-aware interpolation and differencing later on. grid

Y Axis (not periodic, boundary=None): * center nlat_t --> right * right nlat_u --> center Z Axis (not periodic, boundary=None): * center z_t --> left * right z_w_bot --> center * left z_w_top --> center X Axis (not periodic, boundary=None): * center nlon_t --> right * right nlon_u --> center

Calculations

1) Divergence pure xarray version

Note that the pure xarray functions use roll() which basically uses a periodic boundary condition at the domain edges

# using numpy/xarray mix def div_4pt_xr(U, V): """ POP stencil operator for divergence using xarray """ U_at_lat_t=U+U.roll(nlat=1, roll_coords= False) # avg U in y dUdx= U_at_lat_t- U_at_lat_t.roll(nlon=1, roll_coords= False) # dU/dx V_at_lon_t=V+V.roll(nlon=1, roll_coords= False) # avg V in x dVdy= V_at_lon_t- V_at_lon_t.roll(nlat=1, roll_coords= False) # dV/dy return dUdx+ dVdy def divh_xr(U, V, dsgrid): """ calulate divergence """ changed_U= 0.5 * U * dsgrid.DYU * dsgrid.DZU changed_V= 0.5 * V * dsgrid.DXU * dsgrid.DZU div= div_4pt_xr(changed_U, changed_V)/ (dsgrid.TAREA * dsgrid.DZT) return div

48 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

div_xr= divh_xr(ds.UVEL, ds.VVEL, ds) div_xr

array([[[[ nan, 2.82245835e-06, 6.25143603e-06, ..., nan, nan, nan], [ nan, -1.80508841e-08, 8.54803433e-08, ..., nan, nan, nan], [ nan, 4.01141917e-08, 1.07027005e-07, ..., nan, nan, nan], ..., [ 1.52036280e-06, -1.44758122e-08, -3.50509592e-09, ..., -1.28452313e-06, -1.62644312e-06, -1.83187388e-06], [ 1.06668597e-06, -6.68358532e-09, -5.60290977e-08, ..., -5.00422545e-07, -3.13788872e-07, -1.78077049e-07], [-2.87810620e-06, 4.21211314e-09, -7.58155615e-08, ..., 1.14357903e-06, 1.42170407e-06, 1.61619525e-06]],

[[ nan, 1.74533743e-06, 5.22284492e-06, ..., nan, nan, nan], [ nan, 1.08072630e-07, 2.01164913e-07, ..., nan, nan, nan], [ nan, 1.64829881e-07, 2.12093400e-07, ..., nan, nan, nan], ... [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]],

[[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ..., [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]]]]) Coordinates: * time (time) object 0036-12-07 00:00:00 * z_t (z_t) float32 500.0 1.5e+03 2.5e+03 ... 5.625e+05 5.875e+05 ULONG (nlat, nlon) float64 160.0 160.1 160.2 160.3 ... -70.2 -70.1 -70.0 ULAT (nlat, nlon) float64 -15.03 -15.03 -15.03 ... 15.03 15.03 15.03 TLONG (nlat, nlon) float64 159.9 160.0 160.1 160.2 ... 289.8 289.9 290.0 TLAT (nlat, nlon) float64 -15.07 -15.07 -15.07 ... 14.98 14.98 14.98 Dimensions without coordinates: nlat, nlon div_xr.isel(z_t=5, time=0).plot(robust=True, figsize=(10,3)) plt.title("xr divergence @ {:d}m".format(int(div_xr.z_t.isel(z_t=5).values/ 100)));

2.2. Examples 49 POP-tools Documentation, Release 2021.5.28.post11+dirty

Minimal xgcm version

Instead of using xarray’s roll(), we can use xgcm’s diff() and interp():

# using xgcm def div_4pt_xgcm(U, V): # Basic stencil operator for B-grid divergence """ POP stencil operator for divergence using xgcm """ U_at_lat_t= grid.interp(U, axis="Y", boundary="extend") # array - array.roll

˓→becomes interp # -> this incoorporates the * 0.5 dUdx= grid.diff(U_at_lat_t, axis="X", boundary="extend") # - becomes diff V_at_lon_t= grid.interp(V, axis="X", boundary="extend") dVdy= grid.diff(V_at_lon_t, axis="Y", boundary="extend") div_4pt= dUdx+ dVdy return div_4pt def divh_xgcm(U, V, ds_grid): # Divergence of horizontal velocity. Result on T-grid """ calulate divergence with xgcm """ changed_U=U * ds_grid.DYU * ds_grid.DZU changed_V=V * ds_grid.DXU * ds_grid.DZU divh= div_4pt_xgcm(changed_U, changed_V)/ (ds_grid.TAREA * ds_grid.DZT) return divh div_xgcm= divh_xgcm(ds_ren.UVEL, ds_ren.VVEL, ds_ren) div_xgcm

array([[[[ 0.00000000e+00, -1.22930843e-06, -3.79666626e-08, ..., nan, nan, nan], [ 1.29710470e-06, -1.80508841e-08, 8.54803433e-08, ..., nan, nan, nan], [ 4.90406732e-07, 4.01141917e-08, 1.07027005e-07, ..., (continues on next page)

50 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) nan, nan, nan], ..., [ 1.55323600e-07, -1.44758122e-08, -3.50509592e-09, ..., -1.28452313e-06, -1.62644312e-06, -1.83187388e-06], [ 1.10498548e-07, -6.68358532e-09, -5.60290977e-08, ..., -5.00422545e-07, -3.13788872e-07, -1.78077049e-07], [ 1.59686076e-07, 4.21211314e-09, -7.58155615e-08, ..., 1.14357903e-06, 1.42170407e-06, 1.61619525e-06]],

[[ 0.00000000e+00, -1.14137591e-06, 3.27276755e-08, ..., nan, nan, nan], [ 1.33188653e-06, 1.08072630e-07, 2.01164913e-07, ..., nan, nan, nan], [ 5.30723976e-07, 1.64829881e-07, 2.12093400e-07, ..., nan, nan, nan], ... [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]],

[[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ..., [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]]]]) Coordinates: * time (time) object 0036-12-07 00:00:00 * z_t (z_t) float32 500.0 1.5e+03 2.5e+03 ... 5.625e+05 5.875e+05 * nlat_t (nlat_t) float64 0.5 1.5 2.5 3.5 4.5 ... 301.5 302.5 303.5 304.5 * nlon_t (nlon_t) float64 0.5 1.5 2.5 3.5 ... 1.298e+03 1.3e+03 1.3e+03 TLONG (nlat_t, nlon_t) float64 159.9 160.0 160.1 ... 289.8 289.9 290.0 TLAT (nlat_t, nlon_t) float64 -15.07 -15.07 -15.07 ... 14.98 14.98 14.98 div_xgcm.isel(z_t=5, time=0).plot(robust=True, figsize=(10,3)) plt.title("xgcm divergence @ {:d}m".format(int(div_xgcm.z_t.isel(z_t=5).values/

˓→100)));

2.2. Examples 51 POP-tools Documentation, Release 2021.5.28.post11+dirty

This is the same except for boundary points because the pure xarray version assumes that the boundaries are periodic xr.testing.assert_equal( ( div_xgcm.rename( {"nlon_t":"nlon","nlat_t":"nlat"} ) # rename dimensions back to nlon, nlat .assign_coords(nlat=div_xr.nlat, nlon=div_xr.nlon) .reset_coords(drop=True) .isel(nlon=slice(1,-1), nlat=slice(1,-1)) ), ( div_xr.assign_coords(nlat=div_xr.nlat, nlon=div_xr.nlon) .reset_coords(drop=True) .isel(nlon=slice(1,-1), nlat=slice(1,-1)) ), ) xgcm with metrics

If we create an xgcm.Grid object with the metrics term specified, the code can be substantially simplified. For the metric capabilities we will use later on we need to define metrics for pop (this could be moved to pop_tools for convenience so that grid is always created with metrics information). metrics is a dictionary that maps axes names (one of X, Y, Z) to distances along that axis

# pop_tools should handle this bit in the future metrics={ ("X",): ["DXU","DXT"], # X distances ("Y",): ["DYU","DYT"], # Y distances ("Z",): ["DZU","DZT"], # Z distances ("X","Y"): ["UAREA","TAREA"], # areas, technically not needed }

# xgcm metrics gridm, xdsm= pop_tools.to_xgcm_grid_dataset(ds, periodic= False, metrics=metrics)

Note that the code below does not explicitly use DZT or DZU.

52 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

def div_stencil(U, V, grid): # Basic stencil operator for B-grid divergence """ stencil operator for divergence using xgcm.metrics on pop """ U= grid.interp(U, axis="Y", boundary="extend") V= grid.interp(V, axis="X", boundary="extend") dUdx= grid.diff(U, axis="X", boundary="extend") dVdy= grid.diff(V, axis="Y", boundary="extend") div_4pt= dUdx+ dVdy return div_4pt def x_divh(U, V, grid, boundary=None): """ horizontal divergence with xgcm.get_metrics """ dy= grid.get_metric(U,"Y") dx= grid.get_metric(V,"X") dz= grid.get_metric(U,"Z") UT=U * dy * dz VT=V * dx * dz div= div_stencil(UT, VT, grid) volume= grid.get_metric(div,"XYZ") div= div/ volume

return div div_xgcm_m= x_divh(xdsm.UVEL, xdsm.VVEL, gridm) div_xgcm_m

array([[[[ 0.00000000e+00, -1.22930843e-06, -3.79666626e-08, ..., nan, nan, nan], [ 1.29710470e-06, -1.80508841e-08, 8.54803433e-08, ..., nan, nan, nan], [ 4.90406732e-07, 4.01141917e-08, 1.07027005e-07, ..., nan, nan, nan], ..., [ 1.55323600e-07, -1.44758122e-08, -3.50509592e-09, ..., -1.28452313e-06, -1.62644312e-06, -1.83187388e-06], [ 1.10498548e-07, -6.68358532e-09, -5.60290977e-08, ..., -5.00422545e-07, -3.13788872e-07, -1.78077049e-07], [ 1.59686076e-07, 4.21211314e-09, -7.58155615e-08, ..., 1.14357903e-06, 1.42170407e-06, 1.61619525e-06]],

[[ 0.00000000e+00, -1.14137591e-06, 3.27276755e-08, ..., nan, nan, nan], [ 1.33188653e-06, 1.08072630e-07, 2.01164913e-07, ..., nan, nan, nan], [ 5.30723976e-07, 1.64829881e-07, 2.12093400e-07, ..., nan, nan, nan], ... [ nan, nan, nan, ..., nan, nan, nan], (continues on next page)

2.2. Examples 53 POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]],

[[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ..., [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]]]]) Coordinates: * time (time) object 0036-12-07 00:00:00 * z_t (z_t) float32 500.0 1.5e+03 2.5e+03 ... 5.625e+05 5.875e+05 * nlat_t (nlat_t) float64 0.5 1.5 2.5 3.5 4.5 ... 301.5 302.5 303.5 304.5 * nlon_t (nlon_t) float64 0.5 1.5 2.5 3.5 ... 1.298e+03 1.3e+03 1.3e+03

This works as follows: grid.get_metric(U, "Y") tells xgcm to find a DY variable that is at U-points. xgcm checks DYU and DYT (both specified as Y-distances in metrics) and chooses DYU because DYU.dims = (nlat_u, nlon_u) matches U.dims = ("time", "z_t", "nlat_u", "nlon_u") print(xdsm.DYU.dims) print(xdsm.UVEL.dims)

('nlat_u', 'nlon_u') ('time', 'z_t', 'nlat_u', 'nlon_u') xr.testing.assert_equal( gridm.get_metric(xdsm.UVEL,"Y"), xdsm.DYU.reset_coords(drop=True), ) div_xgcm_m.isel(z_t=5, time=0).plot(robust=True, figsize=(10,3)) plt.title("xgcm_metric divergence @ {:d}m".format(int(div_xgcm_m.z_t.isel(z_t=5).

˓→values/ 100)));

54 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

fig, ax= plt.subplots(1,3, figsize=(20,3)) div_xr.isel(z_t=5, time=0).plot(ax=ax[0], robust=True) ax[0].set_title("xarray") div_xgcm.isel(z_t=5, time=0).plot(ax=ax[1], robust=True) ax[1].set_title("xgcm") div_xgcm_m.isel(z_t=5, time=0).plot(ax=ax[2], robust=True) ax[2].set_title("xgcm metrics");

The two xgcm versions agree in the treatment of boundaries, whereas xarray assumes periodic boundaries so that the boundary values differ (the rest are the same): fig, ax= plt.subplots(2,1, figsize=(10, 10)) div_xgcm.isel(nlat_t=0, z_t=0).plot(label="xgcm", ax=ax[0]) div_xgcm_m.isel(nlat_t=0, z_t=0).plot(ls="--", label="metrics", ax=ax[0]) div_xr.isel(nlat=0, z_t=0).plot(label="xr", ax=ax[0], ls=':') ax[0].legend() div_xgcm.isel(nlat_t=1, z_t=0).plot(label="xgcm", ax=ax[1]) div_xgcm_m.isel(nlat_t=1, z_t=0).plot(ls="--", label="metrics", ax=ax[1]) div_xr.isel(nlat=1, z_t=0).plot(label="xr", ax=ax[1], ls=':') ax[1].legend();

2.2. Examples 55 POP-tools Documentation, Release 2021.5.28.post11+dirty

# the two xgcm versions are the same xr.testing.assert_equal(div_xgcm.drop(["TLONG","TLAT"]), div_xgcm_m)

56 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

2) Curl

# define different functions for curl def z_curl_xr(U, V, ds_grid): """ xr based """ vdy= 0.5 * V * ds.DYU udx=-0.5 * U * ds.DXU zcurl= div_4pt_xr(vdy, udx)/ ds.TAREA return zcurl def z_curl_xgcm(U, V, ds_grid): """ xgcm based """ WORKX=V * ds_grid.DYU WORKY=-U * ds_grid.DXU zcurl= div_4pt_xgcm(WORKX, WORKY)/ ds_grid.TAREA return zcurl def x_curlz(U, V, grid): """ xgcm based using metrics """ Udx=U * grid.get_metric(U,"X") Vdy=V * grid.get_metric(V,"Y") der= div_stencil(Vdy,-Udx, grid) area= grid.get_metric(der,"XY") curlz= der/ area return curlz xr_zcurl= z_curl_xr(ds.UVEL, ds.VVEL, ds) xgcm_zcurl= z_curl_xgcm(ds_ren.UVEL, ds_ren.VVEL, ds_ren) xgcm_m_zcurl= x_curlz(ds_ren.UVEL, ds_ren.VVEL, gridm) fig, ax= plt.subplots(1,3, figsize=(20,3)) xr_zcurl.isel(z_t=5, time=0).plot(ax=ax[0], robust=True) ax[0].set_title("xarray") xgcm_zcurl.isel(z_t=5, time=0).plot(ax=ax[1], robust=True) ax[1].set_title("xgcm") xgcm_m_zcurl.isel(z_t=5, time=0).plot(ax=ax[2], robust=True) ax[2].set_title("xgcm metrics");

# test xgcm versions: (continues on next page)

2.2. Examples 57 POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) xr.testing.assert_equal(xgcm_zcurl.drop(["TLONG","TLAT"]), xgcm_m_zcurl)

# test xarray vs xgcm version: xr.testing.assert_equal( ( xr_zcurl.drop(["TLONG","TLAT","ULONG","ULAT"]) .assign_coords(nlat=div_xr.nlat, nlon=div_xr.nlon) .reset_coords(drop=True) .isel(nlon=slice(1,-1), nlat=slice(1,-1)) ), ( xgcm_zcurl.rename({"nlon_t":"nlon","nlat_t":"nlat"}) .assign_coords(nlat=div_xr.nlat, nlon=div_xr.nlon) .reset_coords(drop=True) .isel(nlon=slice(1,-1), nlat=slice(1,-1)) ), )

3) Gradient

# define different functions # xarray def grad_4pt_xr(F): """ gradient stencil using xarray """ WORK2=F.roll(nlat=-1, roll_coords= False) # F[i,j+1] WORK1= WORK2.roll(nlon=-1, roll_coords= False)-F # F[i+1,j+1] - F[i,j] WORK2= WORK2-F.roll(nlon=-1, roll_coords= False) # F[i,j+1] - F[i+1,j] GX= WORK1- WORK2 GY= WORK1+ WORK2 return GX, GY def gradh_xr(F, DX, DY): """ gradient calculation """ GX, GY= grad_4pt_xr(F) GX= 0.5 * GX/DX GY= 0.5 * GY/DY return GX, GY

# xgcm def grad_4pt_xgcm(F): # Basic stencil operator for B-grid gradient (e.g. for

˓→pressure) """ gradient stencil with xgcm """ F_at_lat_u= grid.interp(F, axis="Y", boundary="extend") # 0.5*(F[i,j+1]+F[i,j]) dFdx= grid.diff(F_at_lat_u, axis="X", boundary="extend") F_at_lon_u= grid.interp(F, axis="X", boundary="extend") # 0.5*(F[i+1,j]+F[i,j]) dFdy= grid.diff(F_at_lon_u, axis="Y", boundary="extend") (continues on next page)

58 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) return dFdx, dFdy def gradh_xgcm(F, ds_grid): # Gradient of scalar. Result on U-grid """ gradient of scalar """ GX, GY= grad_4pt_xgcm(F) GX=GX/ ds_grid.DXU GY=GY/ ds_grid.DYU return GX, GY

# xgcm_metrics -> this becomes really easy! def x_gradh(F, grid): """ gradient of scalar xgcm_metrics for pop """ F_yi= grid.interp(F, axis="Y", boundary="extend") # 0.5*(F[i,j+1]+F[i,j]) F_xi= grid.interp(F, axis="X", boundary="extend") # 0.5*(F[i+1,j]+F[i,j]) dFdx= grid.derivative(F_yi, axis="X", boundary="extend") dFdy= grid.derivative(F_xi, axis="Y", boundary="extend") return dFdx, dFdy

# test different versions GX_x, GY_x= gradh_xr(ds.TEMP, ds.DXT, ds.DYU) # xarray version GX_xgcm, GY_xgcm= gradh_xgcm(ds_ren.TEMP, ds_ren) # xgcm version GX_xgcm_m, GY_xgcm_m= x_gradh(ds_ren.TEMP, gridm) # xgcm metrics version fig, ax= plt.subplots(2,3, figsize=(20,6)) GX_x.isel(z_t=5, time=0).plot(ax=ax[0,0], robust= True) ax[0,0].set_title("xarray") GX_xgcm.isel(z_t=5, time=0).plot(ax=ax[0,1], robust= True) ax[0,1].set_title("xgcm") GX_xgcm_m.isel(z_t=5, time=0).plot(ax=ax[0,2], robust= True) ax[0,2].set_title("xgcm metrics")

GY_x.isel(z_t=5, time=0).plot(ax=ax[1,0], robust= True) ax[1,0].set_title("") GY_xgcm.isel(z_t=5, time=0).plot(ax=ax[1,1], robust= True) ax[1,1].set_title("") GY_xgcm_m.isel(z_t=5, time=0).plot(ax=ax[1,2], robust= True) ax[1,2].set_title("");

2.2. Examples 59 POP-tools Documentation, Release 2021.5.28.post11+dirty

# testing xgcm version: xr.testing.assert_equal(GX_xgcm_m, GX_xgcm.drop(["ULONG","ULAT"]))

# testing xarray version xgcm version: xr.testing.assert_allclose( ( GX_x.drop(["TLONG","TLAT","ULONG","ULAT"]) .assign_coords(nlat=div_xr.nlat, nlon=div_xr.nlon) .reset_coords(drop=True) .isel(nlon=slice(1,-1), nlat=slice(1,-1)) ), ( GX_xgcm_m.rename({"nlon_u":"nlon","nlat_u":"nlat"}) .assign_coords(nlat=div_xr.nlat, nlon=div_xr.nlon) .reset_coords(drop=True) .isel(nlon=slice(1,-1), nlat=slice(1,-1)) ), )

%load_ext watermark %watermark -d -iv -m -g

Compiler : Clang 11.0.1 OS : Darwin Release : 19.6.0 Machine : x86_64 Processor : i386 CPU cores : 8 Architecture: 64bit

Git hash: 824cc23a5f921ee3ecf3fe3947cb435dd532e451 xarray : 0.17.0 numpy : 1.20.1 xgcm : 0.5.1 matplotlib: 3.3.4 pop_tools : 2020.12.15.post10+dirty

60 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

2.2.8 Calculate POP2 heat budget using xgcm

In this notebook, we are going to use xgcm with metrics to demonstrate budget closure. This notebook was contributed by Anna-Lena Deppenmeier. This is an image of the POP output structure on the horizontal B-grid courtesy of Yassir Eddebbar.

Import packages and define functions

%matplotlib inline import matplotlib.pyplot as plt import numpy as np import xarray as xr from tqdm import tqdm import pop_tools def pop_find_lat_ind(loc, LATDAT): return np.abs(LATDAT[:,0].values- loc).argmin() def pop_find_lon_ind(loc, LONDAT, direction="w"): if direction.lower() in ["east","e"]: value= loc (continues on next page)

2.2. Examples 61 POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) elif direction.lower() in ["west","w"]: value= 360- loc else: print("I do not know which direction.") return np.nanargmin(np.abs(LONDAT[152, :].values- value))

Load Dataset

# open sample data filepath= pop_tools.DATASETS.fetch('Pac_POP0.1_JRA_IAF_1993-12-6-test.nc') ds= xr.open_dataset(filepath)

# get DZU and DZT, needed for operations later on filepath_g= pop_tools.DATASETS.fetch("Pac_grid_pbc_1301x305x62.tx01_62l.2013-07-13.nc

˓→") ds_g= xr.open_dataset(filepath_g) ds

Dimensions: (nlat: 305, nlon: 1301, time: 1, z_t: 62, z_w: 62, z_w_bot: 62, z_

˓→w_top: 62) Coordinates: * time (time) object 0036-12-07 00:00:00 * z_t (z_t) float32 500.0 1.5e+03 2.5e+03 ... 5.625e+05 5.875e+05 * z_w (z_w) float32 0.0 1e+03 2e+03 ... 5.25e+05 5.5e+05 5.75e+05 * z_w_top (z_w_top) float32 0.0 1e+03 2e+03 ... 5.5e+05 5.75e+05 * z_w_bot (z_w_bot) float32 1e+03 2e+03 3e+03 ... 5.75e+05 6e+05 ULONG (nlat, nlon) float64 ... ULAT (nlat, nlon) float64 ... TLONG (nlat, nlon) float64 ... TLAT (nlat, nlon) float64 ... Dimensions without coordinates: nlat, nlon Data variables: (12/26) TEND_TEMP (time, z_t, nlat, nlon) float32 ... UET (time, z_t, nlat, nlon) float32 ... VNT (time, z_t, nlat, nlon) float32 ... WTT (time, z_w_top, nlat, nlon) float32 ... KPP_SRC_TEMP (time, z_t, nlat, nlon) float32 ... UVEL (time, z_t, nlat, nlon) float32 ...... hflux_factor float64 ... KMT (nlat, nlon) float64 ... KMU (nlat, nlon) float64 ... DIA_IMPVF_TEMP (time, z_w_bot, nlat, nlon) float32 ... SHF (time, nlat, nlon) float32 ... SHF_QSW (time, nlat, nlon) float32 ... Attributes: title: g.e20.G.TL319_t13.control.001_hfreq history: none Conventions: CF-1.0; http://www.cgd.ucar.edu/cms/eaton/netcdf/CF-cu... time_period_freq: day_5 model_doi_url: https://doi.org/10.5065/D67H1H0V contents: Diagnostic and Prognostic Variables (continues on next page)

62 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) source: CCSM POP2, the CCSM Ocean Component revision: $Id: tavg.F90 89091 2018-04-30 15:58:32Z altuntas@ucar... calendar: All years have exactly 365 days. start_time: This dataset was created on 2018-12-14 at 16:05:58.8 cell_methods: cell_methods = time: mean ==> the variable values are ...

# get lola inds from somewhere for indexing later on lola_inds={} inds_lat=[-8,-5,-4,-3,-2,-1,0,1,2,3,4,5,8] for j in inds_lat: if j<0: lola_inds["j_"+ str(j)[1:]+"s"]= pop_find_lat_ind(j, ds_g.TLAT) else: lola_inds["j_"+ str(j)+"n"]= pop_find_lat_ind(j, ds_g.TLAT) inds_lon= range(95, 185,5) for i in inds_lon: lola_inds["i_"+ str(i)+"_w"]= pop_find_lon_ind(i, ds_g.TLONG)

# just making sure everything works ds.TEMP.isel(z_t=0).mean(dim="time").plot(levels=np.arange(20, 30.5, 0.5), cmap=

˓→"RdYlBu_r") plt.scatter(lola_inds["i_140_w"], lola_inds["j_0n"], marker="*");

2.2. Examples 63 POP-tools Documentation, Release 2021.5.28.post11+dirty

Set up vertical thickness and volume for scaling ds["DZT"]= ds_g.DZT ds["DZU"]= ds_g.DZU ds.DZT.attrs["long_name"]="Thickness of T cells" ds.DZT.attrs["units"]="centimeter" ds.DZT.attrs["grid_loc"]="3111" ds.DZU.attrs["long_name"]="Thickness of U cells" ds.DZU.attrs["units"]="centimeter" ds.DZU.attrs["grid_loc"]="3221"

# make sure we have the cell volumne for calculations VOL= (ds.DZT * ds.DXT * ds.DYT).compute() KMT= ds_g.KMT.compute() for j in tqdm(range(len(KMT.nlat))): for i in range(len(KMT.nlon)): k= KMT.values[j, i].astype(int) VOL.values[k:, j, i]= 0.0 ds["VOL"]= VOL ds.VOL.attrs["long_name"]="volume of T cells" ds.VOL.attrs["units"]="centimeter^3" ds.VOL.attrs["grid_loc"]="3111"

100%|| 305/305 [00:01<00:00, 179.47it/s]

Set up dataset to gather budget terms budget= xr.Dataset()

Set grid and data set for xgcm with metrics metrics={ ("X",): ["DXU","DXT"], # X distances ("Y",): ["DYU","DYT"], # Y distances ("Z",): ["DZU","DZT"], # Z distances ("X","Y"): ["UAREA","TAREA"], }

# here we get the xgcm compatible dataset gridxgcm, dsxgcm= pop_tools.to_xgcm_grid_dataset( ds, periodic=False, metrics=metrics, boundary={"X":"extend","Y":"extend","Z":"extend"}, ) for coord in ["nlat","nlon"]: (continues on next page)

64 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) if coord in dsxgcm.coords: dsxgcm= dsxgcm.drop_vars(coord)

0) Tendency budget['TEND_TEMP']= dsxgcm.TEND_TEMP i) Total heat advection budget["UET"]=-(gridxgcm.diff(dsxgcm.UET * dsxgcm.VOL.values, axis="X")/ dsxgcm. ˓→VOL) budget["VNT"]=-(gridxgcm.diff(dsxgcm.VNT * dsxgcm.VOL.values, axis="Y")/ dsxgcm. ˓→VOL) budget["WTT"]=( gridxgcm.diff(dsxgcm.WTT.fillna(0) * (dsxgcm.dz * dsxgcm.DXT * dsxgcm.DYT).values, ˓→ axis="Z") / dsxgcm.VOL ) budget["TOT_ADV"]= budget["UET"]+ budget["VNT"]+ budget["WTT"] ii) Heat flux due to vertical mixing: includes surface flux at the 0th layer budget["DIA_IMPVF_TEMP"]=-( gridxgcm.diff(dsxgcm.DIA_IMPVF_TEMP * dsxgcm.TAREA, axis="Z")/ dsxgcm.VOL )

# set surface flux at 0th layer SRF_TEMP_FLUX= (dsxgcm.SHF- dsxgcm.SHF_QSW) * dsxgcm.hflux_factor budget["DIA_IMPVF_TEMP"][:,0, :, :]=( SRF_TEMP_FLUX * dsxgcm.TAREA- dsxgcm.DIA_IMPVF_TEMP.isel(z_w_bot=0) * dsxgcm. ˓→TAREA )/ dsxgcm.VOL.values[0, :, :] budget["KPP_SRC_TMP"]= dsxgcm.KPP_SRC_TEMP budget["VDIF"]= budget["DIA_IMPVF_TEMP"]+ budget["KPP_SRC_TMP"] iii) Heat flux due to horizontal diffusion budget["HDIFE_TEMP"]= gridxgcm.diff(dsxgcm.HDIFE_TEMP * dsxgcm.VOL.values, axis="X") ˓→/ dsxgcm.VOL budget["HDIFN_TEMP"]= gridxgcm.diff(dsxgcm.HDIFN_TEMP * dsxgcm.VOL.values, axis="Y") ˓→/ dsxgcm.VOL budget["HDIF"]= budget["HDIFE_TEMP"]+ budget["HDIFN_TEMP"]

2.2. Examples 65 POP-tools Documentation, Release 2021.5.28.post11+dirty iv) Solar Penetration budget["QSW_3D"]=-gridxgcm.diff((dsxgcm.QSW_3D * dsxgcm.hflux_factor), axis="Z")/ ˓→dsxgcm.DZT plot to make sure it closes at (0N, 140W) subset= budget.isel(nlon_t=lola_inds["i_140_w"], nlat_t=lola_inds["j_0n"], time=0)

%%time fig, ax= plt.subplots(1,2, figsize=(10,3), sharey= True)

# plot individual components subset.VDIF.plot(y="z_t", ylim=(300e2,0), label="VDIF", ax=ax[0]) subset.HDIF.plot(y="z_t", ylim=(300e2,0), label="HDIF", ax=ax[0]) subset.QSW_3D.plot(y="z_t", ylim=(300e2,0), label="QSW_3D", ax=ax[0]) subset.TOT_ADV.plot(y="z_t", ylim=(300e2,0), label="DIV", ax=ax[0])

# plot sum (subset.QSW_3D+ subset.HDIF+ subset.VDIF+ subset.TOT_ADV).plot( y="z_t", ylim=(300e2,0), label="SUM", ls="--", ax=ax[0] ) # plot tendency subset.TEND_TEMP.plot(y="z_t", ylim=(300e2,0), label="TEND_TEMP", ax=ax[0]) ax[0].legend()

# plot sum (subset.QSW_3D+ subset.HDIF+ subset.VDIF+ subset.TOT_ADV).plot( y="z_t", ylim=(300e2,0), label="SUM", ls="--", ax=ax[1] ) # plot tendency subset.TEND_TEMP.plot(y="z_t", ylim=(300e2,0), label="TEND_TEMP", ax=ax[1]) ax[1].legend();

CPU times: user 126 ms, sys: 4.58 ms, total: 130 ms Wall time: 289 ms

66 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

# You may need to install watermark (conda install -c conda-forge watermark) import xgcm # just to display the version

%load_ext watermark %watermark -d -iv -m -g print("Above are the versions of the packages this works with.")

Compiler : Clang 11.0.1 OS : Darwin Release : 19.6.0 Machine : x86_64 Processor : i386 CPU cores : 8 Architecture: 64bit

Git hash: c1b73199f169ce40d3a7ded125ec0fbbac90b285 matplotlib: 3.3.4 xarray : 0.17.0 xgcm : 0.5.1 numpy : 1.20.1 pop_tools : 2020.12.15.post10+dirty

Above are the versions of the packages this works with.

2.2.9 Nearest-neighbour indexing using xoak

This notebook experiments subsetting datasets using TLONG, TLAT, ULONG, ULAT by making use of the xoak package import matplotlib as mpl import numpy as np import xarray as xr import xoak import pop_tools

# open sample data filepath= pop_tools.DATASETS.fetch('Pac_POP0.1_JRA_IAF_1993-12-6-test.nc') (continues on next page)

2.2. Examples 67 POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) ds= xr.open_dataset(filepath)

# get DZU and DZT, needed for operations later on filepath_g= pop_tools.DATASETS.fetch('Pac_grid_pbc_1301x305x62.tx01_62l.2013-07-13.nc

˓→') ds_g= xr.open_dataset(filepath_g) ds.update(ds_g)

Dimensions: (bnds: 2, nlat: 305, nlon: 1301, time: 1, z_t: 62, z_t_150m:

˓→15, z_w: 62, z_w_bot: 62, z_w_top: 62) Coordinates: * time (time) object 0036-12-07 00:00:00 TLONG (nlat, nlon) float64 ... ULAT (nlat, nlon) float64 ... * z_t (z_t) float32 500.0 1.5e+03 ... 5.625e+05 5.875e+05 TLAT (nlat, nlon) float64 ... ULONG (nlat, nlon) float64 ... * z_t_150m (z_t_150m) float32 500.0 1.5e+03 ... 1.35e+04 1.45e+04 * z_w (z_w) float32 0.0 1e+03 2e+03 ... 5.5e+05 5.75e+05 * z_w_bot (z_w_bot) float32 1e+03 2e+03 3e+03 ... 5.75e+05 6e+05 * z_w_top (z_w_top) float32 0.0 1e+03 2e+03 ... 5.5e+05 5.75e+05 Dimensions without coordinates: bnds, nlat, nlon Data variables: (12/32) time_bnds (time, bnds) object ... UAREA (nlat, nlon) float64 ... TAREA (nlat, nlon) float64 ... DXU (nlat, nlon) float64 ... DYU (nlat, nlon) float64 ... DXT (nlat, nlon) float64 ...... dzw (z_w) float32 ... grav float64 ... nsurface_t float64 ... nsurface_u float64 ... omega float64 ... radius float64 ... Attributes: (12/13) CDI: Climate Data Interface version 1.9.2 (http://mpimet.mp... history: Tue Mar 24 11:51:32 2020: cdo selvar,UVEL,VVEL,DXT,DXU... source: CCSM POP2, the CCSM Ocean Component Conventions: CF-1.0; http://www.cgd.ucar.edu/cms/eaton/netcdf/CF-cu... title: g.e20.G.TL319_t13.control.001_hfreq time_period_freq: day_5 ...... contents: Diagnostic and Prognostic Variables revision: $Id: tavg.F90 89091 2018-04-30 15:58:32Z altuntas@ucar... calendar: All years have exactly 365 days. start_time: This dataset was created on 2018-12-14 at 16:05:58.8 cell_methods: cell_methods = time: mean ==> the variable values are ... CDO: Climate Data Operators version 1.9.2 (http://mpimet.mp... grid, xds= pop_tools.to_xgcm_grid_dataset(ds)

68 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

Set the “index”

This is what allows the indexing magic. xds.xoak.set_index(['TLAT','TLONG'],'scipy_kdtree')

Extracting sections

# have to know that 0.1 is a reasonable choice lons= xr.Variable("points", np.arange(150, 270, 0.1)) lats= xr.zeros_like(lons) eqsection= xds.xoak.sel(TLONG=lons, TLAT=lats)

# plot eqsection.TEMP.sel(z_t=slice(50000)).plot(y="z_t", cmap=mpl.cm.Spectral_r,

˓→yincrease=False)

2.2. Examples 69 POP-tools Documentation, Release 2021.5.28.post11+dirty

Extracting multiple points moorings= xds.xoak.sel( TLONG=xr.Variable("moor",[360- 140, 360- 110]), TLAT=xr.Variable("moor",[0,0]), ) moorings.TEMP.plot(hue="TLONG", y="z_t", yincrease=False)

[, ]

Extracting single points xds.xoak.sel(TLONG=360- 140, TLAT=0).TEMP

------AttributeError Traceback (most recent call last) in ---->1 xds.xoak.sel(TLONG=360- 140, TLAT=0).TEMP

~/miniconda3/envs/dcpy/lib/python3.8/site-packages/xoak/accessor.py in sel(self, ˓→indexers, **indexers_kwargs) 251 252 indexers= either_dict_or_kwargs(indexers, indexers_kwargs,'xoak.sel

˓→') --> 253 indices= self._query(indexers) 254 255 if not isinstance(indices, np.ndarray): (continues on next page)

70 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page)

~/miniconda3/envs/dcpy/lib/python3.8/site-packages/xoak/accessor.py in _query(self,

˓→indexers) 135 136 def _query(self, indexers): --> 137X= coords_to_point_array([indexers[c] for c in self._index_coords]) 138 139 if isinstance(X, np.ndarray) and isinstance(self._index,

˓→XoakIndexWrapper):

~/miniconda3/envs/dcpy/lib/python3.8/site-packages/xoak/accessor.py in coords_to_

˓→point_array(coords) 18 19 """ ---> 20 c_chunks = [c.chunks for c in coords] 21 22 if any([chunks is None for chunks in c_chunks]):

~/miniconda3/envs/dcpy/lib/python3.8/site-packages/xoak/accessor.py in (.0) 18 19 """ ---> 20 c_chunks= [c.chunks for c in coords] 21 22 if any([chunks is None for chunks in c_chunks]):

AttributeError: 'int' object has no attribute 'chunks' xoak expectes “trajectories” to sample along. For a single point we create a 1D variable representing the coordi- nate location we want: in this case TLONG=220, TLAT=0. Seems like this could be fixed: https://github.com/ xarray-contrib/xoak/issues/37 xds.xoak.sel( TLONG=xr.Variable("points",[360- 140]), TLAT=xr.Variable("points",[0]) ).TEMP.squeeze("points")

array([[25.794353 , 25.759989 , 25.728874 , 25.674746 , 25.541134 , 25.282745 , 25.026842 , 24.813889 , 24.512192 , 23.9899 , 22.513605 , 21.532747 , 21.387815 , 20.417183 , 19.48939 , 18.584412 , 17.558277 , 16.449156 , 15.601459 , 14.897679 , 14.326382 , 13.539371 , 12.851948 , 12.320872 , 11.637564 , 11.112046 , 10.732501 , 10.340948 , 9.864892 , 9.434968 , 9.031752 , 8.564738 , 8.070933 , 7.620849 , 7.1164446 , 6.5846534 , 6.0993133 , 5.625975 , 5.127931 , 4.5544333 , 4.004363 , 3.477641 , 3.0496979 , 2.6729817 , 2.360019 , 2.0861135 , 1.8473006 , 1.6999204 , 1.5623759 , 1.4673579 , 1.3774252 , 1.2729893 , 1.1820002 , 1.0894325 , 0.99818563, 0.9394488 , nan, nan, nan, nan, nan, nan]], dtype=float32) Coordinates: * time (time) object 0036-12-07 00:00:00 TLONG float64 220.0 * z_t (z_t) float32 500.0 1.5e+03 2.5e+03 ... 5.625e+05 5.875e+05 TLAT float64 -0.05 nlon_t float64 600.5 nlat_t float64 152.5 (continues on next page)

2.2. Examples 71 POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) Attributes: long_name: Potential Temperature units: degC grid_loc: 3111 cell_methods: time: mean

Limitations

• [ ] cannot simply index by point • [ ] Can only set one index at a time (so only, TLONG, TLAT or ULONG, ULAT) • [ ] indexes are not propagated so xds.TEMP.xoak will only work after xds.TEMP.set_index is called xds.TEMP.xoak.sel(TLONG=220, TLAT=0)

------ValueError Traceback (most recent call last) in ---->1 xds.TEMP.xoak.sel(TLONG=220, TLAT=0)

~/miniconda3/envs/dcpy/lib/python3.8/site-packages/xoak/accessor.py in sel(self, ˓→indexers, **indexers_kwargs) 246 """ 247 if not getattr(self,'_index', False): --> 248 raise ValueError( 249'The index(es) has/have not been built yet. Call `.xoak.set_

˓→index()` first' 250)

ValueError: The index(es) has/have not been built yet. Call `.xoak.set_index()` first xds.xoak.sel(TLONG=220, TLAT=0)

------AttributeError Traceback (most recent call last) in ---->1 xds.xoak.sel(TLONG=220, TLAT=0)

~/miniconda3/envs/dcpy/lib/python3.8/site-packages/xoak/accessor.py in sel(self, ˓→indexers, **indexers_kwargs) 251 252 indexers= either_dict_or_kwargs(indexers, indexers_kwargs,'xoak.sel

˓→') --> 253 indices= self._query(indexers) 254 255 if not isinstance(indices, np.ndarray):

~/miniconda3/envs/dcpy/lib/python3.8/site-packages/xoak/accessor.py in _query(self,

˓→indexers) 135 136 def _query(self, indexers): --> 137X= coords_to_point_array([indexers[c] for c in self._index_coords]) 138 139 if isinstance(X, np.ndarray) and isinstance(self._index, ˓→XoakIndexWrapper): (continues on next page)

72 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page)

~/miniconda3/envs/dcpy/lib/python3.8/site-packages/xoak/accessor.py in coords_to_

˓→point_array(coords) 18 19 """ ---> 20 c_chunks = [c.chunks for c in coords] 21 22 if any([chunks is None for chunks in c_chunks]):

~/miniconda3/envs/dcpy/lib/python3.8/site-packages/xoak/accessor.py in (.0) 18 19 """ ---> 20 c_chunks= [c.chunks for c in coords] 21 22 if any([chunks is None for chunks in c_chunks]):

AttributeError: 'int' object has no attribute 'chunks'

%load_ext watermark %watermark -d -iv -m -g

Compiler : GCC 9.3.0 OS : Linux Release : 5.8.0-44-generic Machine : x86_64 Processor : x86_64 CPU cores : 8 Architecture: 64bit

Git hash: bd1236ca615b32595c43cfa689e85fc9a112eb9f numpy : 1.20.1 xoak : 0.1.0 xarray : 0.17.1.dev3+g48378c4b1 matplotlib: 3.3.4 pop_tools : 2020.12.15.post6+dirty

2.3 API Reference

This page provides an auto-generated summary of pop-tool’s API. For more details and examples, refer to the relevant chapters in the main part of the documentation.

2.3.1 Grid

get_grid(grid_name[, scrip]) Return a xarray.Dataset() with POP grid variables.

2.3. API Reference 73 POP-tools Documentation, Release 2021.5.28.post11+dirty

2.3.2 Equation of State

eos(salt, temp[, return_coefs]) Compute density as a function of salinity, temperature, and depth (or pressure). compute_pressure Convert depth in meters to pressure in bars.

2.3.3 Calculations

cfc11sol(SALT, TEMP) Compute CFC11 solubility in seawater. Reference: Warner & Weiss (1985) , Deep Sea Research, vol32 doi:10.1016/0198-0149(85)90099-8. cfc12sol(SALT, TEMP) Compute CFC12 solubility in seawater. Reference: Warner & Weiss (1985) , Deep Sea Research, vol32 doi:10.1016/0198-0149(85)90099-8.

2.3.4 Region masks

region_mask_3d(grid_name[, mask_name, . . . ]) Generate as 3-D region mask with dimensions (‘region’, ‘nlat’, ‘nlon’). list_region_masks(grid_name) Get a list of the pre-defined region masks.

2.3.5 Utilities

lateral_fill(da_in, isvalid_mask[, . . . ]) Perform lateral fill on xarray.DataArray

2.3.6 xgcm utilities

to_xgcm_grid_dataset(ds, **kwargs) Modify POP model output to be compatible with xgcm. pop_tools.get_grid(grid_name, scrip=False) Return a xarray.Dataset() with POP grid variables. Parameters • grid_name (str) – Name of grid (i.e., POP_gx3v7, POP_gx1v7, POP_tx0.1v3) • scrip (boolean, optional) – Return grid in SCRIP format Returns dso (xarray.Dataset) – Dataset containing POP grid variables. pop_tools.eos(salt, temp, return_coefs=False, **kwargs) Compute density as a function of salinity, temperature, and depth (or pressure). McDougall, T.J., D.R. Jackett, D.G. Wright, and R. Feistel, 2003: Accurate and Computationally Efficient Algorithms for Potential Temperature and Density of Seawater. J. Atmos. Oceanic Technol., 20, 730–741, https://doi.org/10.1175/1520-0426(2003)20<730:AACEAF>2.0.CO;2. test value: rho = 1033.213387 kg/m^3; S = 35.0 PSU, theta = 20.0 C, pressure = 2000.0 dbars

74 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

Parameters • salt (float) – salinity, psu • temp (float) – potential temperature, degree C • return_coefs (boolean, optional [default=False]) – Logical, if true function returns 2 additional arguments: dRHOdS and dRHOdT • depth (float, optional) – depth in meters, if not provided, pressure must be provided. • pressure (float, optional) – depth in dbar Returns • rho (float) – density kg/m^3 • dRHOdS (float, optional) – Derivative of rho with respect to salinity. • dRHOdT (float, optional) – Derivative of rho with respect to temperature. pop_tools.compute_pressure() Convert depth in meters to pressure in bars. Parameters depth (float) – Depth in meters Returns pressure (float) – Pressure in dbar pop_tools.region_mask_3d(grid_name, mask_name=None, region_defs=None) Generate as 3-D region mask with dimensions (‘region’, ‘nlat’, ‘nlon’). Parameters • grid_name (str) – Name of grid (i.e., POP_gx3v7, POP_gx1v7, POP_tx0.1v3) • mask_name (str, optional) – Name of the pre-defined mask. If not provided and re- gion_defs is not provided, the default REGION_MASK is used. • region_defs (dict, optional) – Dictionary containing region definitions. The dictionary has the following form: region_defs = {region1_name: list_of_criteria_dicts_1, region2_name: list_of_criteria_dicts_2,. . . } list_of_criteria_dicts is a list of dictionaries; each must include the keys ‘match’ or ‘bounds’. For instance: list_of_criteria_dicts = [{‘match’: {‘REGION_MASK’: [1, 2, 3, 6]}, ‘bounds’: {‘TLAT’: [-90., -30.]}}] will identify a region where the default POP grid REGION_MASK values match the spec- ified list and TLAT is between 90°S and 30°S. Multiple entries in the list_of_criteria_dicts are applied with an “or” condition. Returns mask3d (xarray.DataArray) – Region mask DataArray with dimensions (‘region’, ‘nlat’, ‘nlon’). mask3d has “ones” within a region and “zeroes” outside it. A region coordinate is included that contains the region names. pop_tools.list_region_masks(grid_name) Get a list of the pre-defined region masks. Parameters grid_name (str) – Name of grid (i.e., POP_gx3v7, POP_gx1v7, POP_tx0.1v3) Returns region_mask_list (list) – List of defined region mask names.

2.3. API Reference 75 POP-tools Documentation, Release 2021.5.28.post11+dirty pop_tools.lateral_fill(da_in, isvalid_mask, ltripole=False, tol=0.0001, use_sor=False, rc=1.8, max_iter=10000) Perform lateral fill on xarray.DataArray Parameters • da_in (xarray.DataArray) – DataArray on which to fill NaNs. Fill is performed on the two rightmost dimenions. Grid is assumed periodic in x direction (last dimension). • isvalid_mask (xarray.DataArray, boolean) – Valid values mask: True where data should be filled. Must have the same rightmost dimenions as da_in. • ltripole (boolean, optional [default=False]) – Logical flag; if True then treat the top row of the grid as periodic in the sense of a tripole grid. tol [float, optional [default=1.0e-4]] Convergence criteria: stop filling when values change is less or equal to tol * var; i.e. delta <= tol * np.abs(var[j, i]). • use_sor (boolean, optional [default=False]) – switch to select SOR fill algo- rithm over progressive fill algorithm • rc (float, optional [default=1.8, valid bounds=(1.0,2.0)]) – over- relaxation coefficient to use in SOR fill algorithm. Larger arrrays (or extent of region to be filled if not global) typically converge faster with larger coefficients. For completely land-filling a 1 deg. grid (360x180) a coefficient in the range 1.85-1.9 is near optimal. • max_iter (integer, optional, [default=10000]) – maximum number of iterations to do before giving up if tol is not reached. Returns da_out (xarray.DataArray) – DataArray with NaNs filled by iterative smoothing. pop_tools.to_xgcm_grid_dataset(ds, **kwargs) Modify POP model output to be compatible with xgcm. Parameters • ds (xarray.Dataset) – An xarray Dataset • kwargs – Additional keyword arguments are passed through to xgcm.Grid class. Returns • grid (xgcm.Grid) – An xgcm Grid object • ds_new (xarray.Dataset) – Xarray dataset with distinct dimensions for variables at different grid points.

Examples

>>> from pop_tools import DATASETS >>> import xarray as xr >>> filepath= DATASETS.fetch("g.e20.G.TL319_t13.control.001_hfreq-coarsen.nc") >>> ds= xr.open_dataset(filepath) >>> ds Dimensions: (d2: 2, nlat: 240, nlon: 360, time: 1, z_t: 62, z_t_150m: 15,

˓→ z_w: 62, z_w_top: 62) Coordinates: * time (time) object 0050-01-01 00:00:00 * z_t (z_t) float32 500.0 1500.0 2500.0 ... 562499.06 587499.06 * z_t_150m (z_t_150m) float32 500.0 1500.0 2500.0 ... 13500.0 14500.0 (continues on next page)

76 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) * z_w (z_w) float32 0.0 1000.0 2000.0 ... 549999.06 574999.06 * z_w_top (z_w_top) float32 0.0 1000.0 2000.0 ... 549999.06 574999.06 TLONG (nlat, nlon) float64 ... TLAT (nlat, nlon) float64 ... Dimensions without coordinates: d2, nlat, nlon Data variables: dz (z_t) float32 ... dzw (z_w) float32 ... KMT (nlat, nlon) float64 ... REGION_MASK (nlat, nlon) float64 ... TAREA (nlat, nlon) float64 ... DXU (nlat, nlon) float64 ... DYU (nlat, nlon) float64 ... DYT (nlat, nlon) float64 ... time_bound (time, d2) object ... UEU (time, z_t, nlat, nlon) float32 ... VNU (time, z_t, nlat, nlon) float32 ... S_FLUX_ROFF_VSF (time, z_w_top, nlat, nlon) float32 ... >>> grid, ds_new= to_xgcm_grid_dataset(ds) >>> grid X Axis (periodic): * center nlon_t --> right * right nlon_u --> center Z Axis (periodic): * center z_t --> left * left z_w_top --> center Y Axis (periodic): * center nlat_t --> right * right nlat_u --> center >>> ds_new Dimensions: (d2: 2, nlat_t: 240, nlat_u: 240, nlon_t: 360, nlon_u: 360,

˓→time: 1, z_t: 62, z_t_150m: 15, z_w: 62, z_w_top: 62) Coordinates: * time (time) object 0050-01-01 00:00:00 * z_t (z_t) float32 500.0 1500.0 2500.0 ... 562499.06 587499.06 * z_t_150m (z_t_150m) float32 500.0 1500.0 2500.0 ... 13500.0 14500.0 * z_w (z_w) float32 0.0 1000.0 2000.0 ... 549999.06 574999.06 * z_w_top (z_w_top) float32 0.0 1000.0 2000.0 ... 549999.06 574999.06 TLONG (nlat_t, nlon_t) float64 nan nan nan nan ... nan nan nan TLAT (nlat_t, nlon_t) float64 nan nan nan nan ... nan nan nan * nlon_u (nlon_u) int64 1 2 3 4 5 6 7 ... 355 356 357 358 359 360 * nlat_u (nlat_u) int64 1 2 3 4 5 6 7 ... 235 236 237 238 239 240 * nlon_t (nlon_t) float64 0.5 1.5 2.5 3.5 ... 357.5 358.5 359.5 * nlat_t (nlat_t) float64 0.5 1.5 2.5 3.5 ... 237.5 238.5 239.5 Dimensions without coordinates: d2 Data variables: dz (z_t) float32 ... dzw (z_w) float32 ... KMT (nlat_t, nlon_t) float64 nan nan nan nan ... nan nan nan REGION_MASK (nlat_t, nlon_t) float64 nan nan nan nan ... nan nan nan TAREA (nlat_t, nlon_t) float64 nan nan nan nan ... nan nan nan DXU (nlat_u, nlon_u) float64 nan nan nan nan ... nan nan nan DYU (nlat_u, nlon_u) float64 nan nan nan nan ... nan nan nan DYT (nlat_t, nlon_t) float64 nan nan nan nan ... nan nan nan time_bound (time, d2) object ... (continues on next page)

2.3. API Reference 77 POP-tools Documentation, Release 2021.5.28.post11+dirty

(continued from previous page) UEU (time, z_t, nlat_u, nlon_u) float32 inf inf inf ... inf inf VNU (time, z_t, nlat_t, nlon_u) float32 inf inf inf ... inf inf S_FLUX_ROFF_VSF (time, z_w, nlat_t, nlon_t) float32 inf inf inf ... inf inf pop_tools.cfc11sol(SALT, TEMP) Compute CFC11 solubility in seawater. Reference: Warner & Weiss (1985) , Deep Sea Research, vol32 doi:10.1016/0198-0149(85)90099-8

Parameters • SALT (float) – salinity, psu • TEMP (float) – potential temperature, degree C Returns SOLUBILITY_CFC11 (returned value in mol/m3/patm) pop_tools.cfc12sol(SALT, TEMP) Compute CFC12 solubility in seawater. Reference: Warner & Weiss (1985) , Deep Sea Research, vol32 doi:10.1016/0198-0149(85)90099-8

Parameters • SALT (float) – salinity, psu • TEMP (float) – potential temperature, degree C Returns SOLUBILITY_CFC12 (returned value in mol/m3/patm)

2.4 Contributing Guide

• Contributing Guide – Feature requests and feedback – Report bugs – Fix bugs – Write documentation – Preparing Pull Requests Interested in helping build pop-tools? Have code from your work that you believe others will find useful? Have a few minutes to tackle an issue? Contributions are highly welcomed and appreciated. Every little help counts, so do not hesitate! The following sections cover some general guidelines regarding development in pop-tools for maintainers and con- tributors. Nothing here is set in stone and can’t be changed. Feel free to suggest improvements or changes in the workflow.

78 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

2.4.1 Feature requests and feedback

We’d also like to hear about your propositions and suggestions. Feel free to submit them as issues on pop-tools’s GitHub issue tracker and: • Explain in detail how they should work. • Keep the scope as narrow as possible. This will make it easier to implement.

2.4.2 Report bugs

Report bugs for pop-tools in the issue tracker. If you are reporting a bug, please include: • Your operating system name and version. • Any details about your local setup that might be helpful in troubleshooting, specifically the Python interpreter version, installed libraries, and pop-tools version. • Detailed steps to reproduce the bug. If you can write a demonstration test that currently fails but should pass (xfail), that is a very useful commit to make as well, even if you cannot fix the bug itself.

2.4.3 Fix bugs

Look through the GitHub issues for bugs. Talk to developers to find out how you can fix specific bugs.

2.4.4 Write documentation pop-tools could always use more documentation. What exactly is needed? • More complementary documentation. Have you perhaps found something unclear? • Docstrings. There can never be too many of them. • Blog posts, articles and such – they’re all very appreciated. You can also edit documentation files directly in the GitHub web interface, without using a local copy. This can be convenient for small fixes. Build the documentation locally with the following command:

$ make docs

2.4. Contributing Guide 79 POP-tools Documentation, Release 2021.5.28.post11+dirty

2.4.5 Preparing Pull Requests

1. Fork the pop-tools GitHub repository. 2. Clone your fork locally using git, connect your repository to the upstream (main project), and create a branch::

$ git clone [email protected]:YOUR_GITHUB_USERNAME/pop-tools.git $ cd pop-tools $ git remote add upstream [email protected]:NCAR/pop-tools.git

now, to fix a bug or add feature create your own branch off “master”:

$ git checkout -b your-bugfix-feature-branch-name master

If you need some help with Git, follow this quick start guide: https://git.wiki.kernel.org/index.php/QuickStart 3. Install dependencies into a new conda environment::

$ conda env update -f ci/environment.yml $ conda activate pop-tools-dev

4. Make an editable install of pop-tools by running::

$ python -m pip install -e .

5. Install pre-commit hooks on the pop-tools repo::

$ pre-commit install

Afterwards pre-commit will run whenever you commit. pre-commit is a framework for managing and maintaining multi-language pre-commit hooks to ensure code- style and code formatting is consistent. Now you have an environment called pop-tools-dev that you can work in. You’ll need to make sure to activate that environment next time you want to use it after closing the terminal or your system. 6. (Optional) Run all the tests Now running tests is as simple as issuing this command::

$ pytest --cov=./

This command will run tests via the pytest tool. 7. Commit and push once your tests pass and you are happy with your change(s):: When committing, pre-commit will re-format the files if necessary.

$ git commit -a -m "" $ git push -u

8. Finally, submit a pull request through the GitHub website using this data::

head-fork: YOUR_GITHUB_USERNAME/pop-tools compare: your-branch-name

base-fork: NCAR/pop-tools base: master # if it's a bugfix or feature

80 Chapter 2. Get in touch POP-tools Documentation, Release 2021.5.28.post11+dirty

2.5 Changelog

2.5.1 v2021.5.28

(full changelog)

New Features

• Added CFC solubility functions #91(@matt-long) • Extend to_xgcm_grid_dataset() to support POP datasets with non canonical dimensions #94(@an- dersy005)

Breaking Changes

• Upgrade minimum Python version to 3.7 #79(@andersy005) • Upgrade dependencies and pin minimum versions #68(@andersy005)

Bug Fixes

• Update pooch downloader: use CESMDATAROOT variable when available #52(@andersy005)

Documentation

• Experiment with using xoak for indexing #84(@dcherian) • Documentation cleanup #81(@andersy005) • Fix Typo in docs #80(@andersy005) • Remove sticky sidebar due to responsiveness issues on small screens #77(@andersy005) • Add example notebook to demonstrate POP2 heat budget closure with xgcm metrics #75(@ALDepp) • New docs theme & Add comments #74(@andersy005) • Use execution_excludepatterns to exclude long running notebooks #76(@andersy005)

Internal Changes

• Bump pre-commit/action from v2.0.2 to v2.0.3 #92(@dependabot) • Bump pre-commit/action from v2.0.0 to v2.0.2 #90(@dependabot) • Bump styfle/cancel-workflow-action from 0.8.0 to 0.9.0 #89(@dependabot) • Update CI #78(@andersy005)

2.5. Changelog 81 POP-tools Documentation, Release 2021.5.28.post11+dirty

Contributors to this release

(GitHub contributors page for this release) @ALDepp| @andersy005| @dcherian| @dependabot| @Eddebbar| @matt-long| @mgrover1

2.5.2 v2020.12.15

(full changelog)

Internal Changes

• Upgrade dependencies and pin minimum versions #68(@andersy005) • Migrate CI from CircleCI to GHA #67(@andersy005) • Use vectorize instead of jit in EOS #66(@rabernat) • Update pooch downloader: use CESMDATAROOT variable when available #52(@andersy005)

Contributors to this release

(GitHub contributors page for this release) @andersy005| @klindsay28| @kmpaul| @matt-long| @rabernat

82 Chapter 2. Get in touch INDEX

C cfc11sol() (in module pop_tools), 78 cfc12sol() (in module pop_tools), 78 compute_pressure() (in module pop_tools), 75 E eos() (in module pop_tools), 74 G get_grid() (in module pop_tools), 74 L lateral_fill() (in module pop_tools), 75 list_region_masks() (in module pop_tools), 75 R region_mask_3d() (in module pop_tools), 75 T to_xgcm_grid_dataset() (in module pop_tools), 76

83