In this notebook we demonstrate all of netCDF-SCM’s known weightings. These weights are used when taking area overages for different SCM boxes e.g. the ocean/land boxes or the El Nino box.

Note: here we use the “last resort” land surface fraction values. However, if land surface fraction data is available then that is used to do land/ocean weighting rather than the “last resort” values.

This notebook is set out as follows:

  1. we show the default weights

  2. we show how the different available options for combining area and surface fraction information

  3. we show all our inbuilt weights

  4. we show how the user can define their own custom weights.


from os.path import join

import iris
import iris.quickplot as qplt
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import regionmask

from netcdf_scm.iris_cube_wrappers import CMIP6OutputCube
from netcdf_scm.weights import (
%matplotlib inline

Data path

Here we use our test data.

DATA_PATH_TEST = join("..", "..", "..", "tests", "test-data")

Load the cube

example = CMIP6OutputCube()
        #         "CMIP6/ScenarioMIP/BCC/BCC-CSM2-MR/ssp126/r1i1p1f1/Amon/example/gn/v20190314",

Interpolate the cube to get higher resolution data.

sample_points = [
    ("longitude", np.arange(0, 360, 2)),
    ("latitude", np.arange(-90, 90 + 1, 2)),
example.cube = example.cube.interpolate(sample_points, iris.analysis.Linear())


Default weights

By default, only land/ocean and hemispheric weights are considered.

default_weights = example.get_scm_timeseries_weights()
/Users/znicholls/miniconda3/envs/netcdf-scm/lib/python3.9/site-packages/iris/analysis/cartography.py:394: UserWarning: Using DEFAULT_SPHERICAL_EARTH_RADIUS.
  warnings.warn("Using DEFAULT_SPHERICAL_EARTH_RADIUS.")
def plot_weights(weights_to_plot, constraint=None, axes=None, **kwargs):
    for i, (label, weights) in enumerate(weights_to_plot.items()):
        if axes is None:
            ax = plt.figure().add_subplot(111)
            ax = axes[i]

        weight_cube = example.cube.collapsed("time", iris.analysis.MEAN)
        weight_cube.data = weights
        weight_cube.units = ""
        if constraint is not None:
            weight_cube = weight_cube.extract(constraint)


            weight_cube, **kwargs,



Area and surface fraction combination options

By defaults, the weights are calculated as the combination of area and surface fractions using netcdf_scm.weights.AreaSurfaceFractionWeightCalculator.


    Calculates weights which are both area and surface fraction weighted

    .. math::

        w(lat, lon) = a(lat, lon) \\times s(lat, lon)

    where :math:`w(lat, lon)` is the weight of the cell at given latitude and
    longitude, :math:`a` is area of the cell and :math:`s` is the surface
    fraction of the cell (e.g. fraction of ocean area for ocean based regions).

For land/ocean weights, this causes regions on coastlines to have weights less than their area weight, because they are not fully land or ocean.

The user can instead use netcdf_scm.weights.AreaWeightCalculator, which focusses on area weights but removes any areas that have a surface fraction of zero.


    Calculates weights which are area weighted but surface fraction aware.

    This means that any cells which have a surface fraction of zero will
    receive zero weight, otherwise cells are purely area weighted.

    .. math::

        w(lat, lon) = \\begin{cases}
            a(lat, lon), & s(lat, lon) > 0 \\\\
            0, & s(lat, lon) = 0

    where :math:`w(lat, lon)` is the weight of the cell at given latitude and
    longitude, :math:`a` is area of the cell and :math:`s` is the surface
    fraction of the cell (e.g. fraction of ocean area for ocean based regions).

area_weights = example.get_scm_timeseries_weights(cell_weights="area-only")
/Users/znicholls/miniconda3/envs/netcdf-scm/lib/python3.9/site-packages/iris/analysis/cartography.py:394: UserWarning: Using DEFAULT_SPHERICAL_EARTH_RADIUS.
  warnings.warn("Using DEFAULT_SPHERICAL_EARTH_RADIUS.")
fig, axes = plt.subplots(figsize=(16, 9), nrows=2, ncols=2)

for i, (w, title) in enumerate(
    ((default_weights, "Default"), (area_weights, "No land fraction"))
    plt_weights = {k: w[k] for k in ["World|Ocean", "World|Land"]}
    zoom_constraint = iris.Constraint(
        latitude=lambda cell: -45 < cell < -25
    ) & iris.Constraint(longitude=lambda cell: 120 < cell < 160)
        plt_weights, constraint=zoom_constraint, axes=[axes[0][i], axes[1][i]],

cf = plt.gcf()
for i, (w, title) in enumerate(
    ((default_weights, "Default"), (area_weights, "Area only"))
    title_ax = cf.axes[i * 4]
    title_ax.set_title("{}\n{}".format(title, title_ax.get_title()))

All inbuilt masks

The default masks do not contain all inbuilt masks. We also provide masks for the IPCC AR6 regions, as defined in Iturbide et al. (2020), as well as country-level (at the 50m scale) masks defined by Natural Earth. For both these masks, we use the regionmask implementation.

The regionmask names can be inspected as shown below. Not that the abbreviations for the countries are not unique.

regionmask_countries = (
            "name": regionmask.defined_regions.natural_earth.countries_50.names,
            "abbreviation": regionmask.defined_regions.natural_earth.countries_50.abbrevs,
name abbreviation
0 Afghanistan AF
1 Albania AL
2 Algeria DZ
3 American Samoa AS
4 Andorra AND
... ... ...
236 Yemen YE
237 Zambia ZM
238 Zimbabwe ZW
239 eSwatini SW
240 Åland AI

241 rows × 2 columns

Below we show a selection of plots for the regions we include.

selection_inbuilt_weights = example.get_scm_timeseries_weights(
        "World|Northern Hemisphere",
        "World|Southern Hemisphere",
        "World|Northern Hemisphere|Land",
        "World|Southern Hemisphere|Land",
        "World|Northern Hemisphere|Ocean",
        "World|Southern Hemisphere|Ocean",
        "World|North Atlantic Ocean",
        "World|El Nino N3.4",
    + [
        "World|Natural Earth 50m|{}".format(c)
        for c in [
            "New Zealand",
            "United States of America",
            # this fails as the region is tiny and
            # our data is not high-resolution enough to capture it
/Users/znicholls/Documents/AGCEC/netCDF-SCM/netcdf-scm/src/netcdf_scm/weights/__init__.py:869: UserWarning: Failed to create 'World|Natural Earth 50m|Vatican' weights: All weights are zero for region: `World|Natural Earth 50m|Vatican`
<ipython-input-7-e10806626a7c>:5: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).
  ax = plt.figure().add_subplot(111)
# full list of available regions
 'World|El Nino N3.4',
 'World|Natural Earth 50m|Afghanistan',
 'World|Natural Earth 50m|Albania',
 'World|Natural Earth 50m|Algeria',
 'World|Natural Earth 50m|American Samoa',
 'World|Natural Earth 50m|Andorra',
 'World|Natural Earth 50m|Angola',
 'World|Natural Earth 50m|Anguilla',
 'World|Natural Earth 50m|Antarctica',
 'World|Natural Earth 50m|Antigua and Barb.',
 'World|Natural Earth 50m|Argentina',
 'World|Natural Earth 50m|Armenia',
 'World|Natural Earth 50m|Aruba',
 'World|Natural Earth 50m|Ashmore and Cartier Is.',
 'World|Natural Earth 50m|Australia',
 'World|Natural Earth 50m|Austria',
 'World|Natural Earth 50m|Azerbaijan',
 'World|Natural Earth 50m|Bahamas',
 'World|Natural Earth 50m|Bahrain',
 'World|Natural Earth 50m|Bangladesh',
 'World|Natural Earth 50m|Barbados',
 'World|Natural Earth 50m|Belarus',
 'World|Natural Earth 50m|Belgium',
 'World|Natural Earth 50m|Belize',
 'World|Natural Earth 50m|Benin',
 'World|Natural Earth 50m|Bermuda',
 'World|Natural Earth 50m|Bhutan',
 'World|Natural Earth 50m|Bolivia',
 'World|Natural Earth 50m|Bosnia and Herz.',
 'World|Natural Earth 50m|Botswana',
 'World|Natural Earth 50m|Br. Indian Ocean Ter.',
 'World|Natural Earth 50m|Brazil',
 'World|Natural Earth 50m|British Virgin Is.',
 'World|Natural Earth 50m|Brunei',
 'World|Natural Earth 50m|Bulgaria',
 'World|Natural Earth 50m|Burkina Faso',
 'World|Natural Earth 50m|Burundi',
 'World|Natural Earth 50m|Cabo Verde',
 'World|Natural Earth 50m|Cambodia',
 'World|Natural Earth 50m|Cameroon',
 'World|Natural Earth 50m|Canada',
 'World|Natural Earth 50m|Cayman Is.',
 'World|Natural Earth 50m|Central African Rep.',
 'World|Natural Earth 50m|Chad',
 'World|Natural Earth 50m|Chile',
 'World|Natural Earth 50m|China',
 'World|Natural Earth 50m|Colombia',
 'World|Natural Earth 50m|Comoros',
 'World|Natural Earth 50m|Congo',
 'World|Natural Earth 50m|Cook Is.',
 'World|Natural Earth 50m|Costa Rica',
 'World|Natural Earth 50m|Croatia',
 'World|Natural Earth 50m|Cuba',
 'World|Natural Earth 50m|Curaçao',
 'World|Natural Earth 50m|Cyprus',
 'World|Natural Earth 50m|Czechia',
 "World|Natural Earth 50m|Côte d'Ivoire",
 'World|Natural Earth 50m|Dem. Rep. Congo',
 'World|Natural Earth 50m|Denmark',
 'World|Natural Earth 50m|Djibouti',
 'World|Natural Earth 50m|Dominica',
 'World|Natural Earth 50m|Dominican Rep.',
 'World|Natural Earth 50m|Ecuador',
 'World|Natural Earth 50m|Egypt',
 'World|Natural Earth 50m|El Salvador',
 'World|Natural Earth 50m|Eq. Guinea',
 'World|Natural Earth 50m|Eritrea',
 'World|Natural Earth 50m|Estonia',
 'World|Natural Earth 50m|Ethiopia',
 'World|Natural Earth 50m|Faeroe Is.',
 'World|Natural Earth 50m|Falkland Is.',
 'World|Natural Earth 50m|Fiji',
 'World|Natural Earth 50m|Finland',
 'World|Natural Earth 50m|Fr. Polynesia',
 'World|Natural Earth 50m|Fr. S. Antarctic Lands',
 'World|Natural Earth 50m|France',
 'World|Natural Earth 50m|Gabon',
 'World|Natural Earth 50m|Gambia',
 'World|Natural Earth 50m|Georgia',
 'World|Natural Earth 50m|Germany',
 'World|Natural Earth 50m|Ghana',
 'World|Natural Earth 50m|Greece',
 'World|Natural Earth 50m|Greenland',
 'World|Natural Earth 50m|Grenada',
 'World|Natural Earth 50m|Guam',
 'World|Natural Earth 50m|Guatemala',
 'World|Natural Earth 50m|Guernsey',
 'World|Natural Earth 50m|Guinea',
 'World|Natural Earth 50m|Guinea-Bissau',
 'World|Natural Earth 50m|Guyana',
 'World|Natural Earth 50m|Haiti',
 'World|Natural Earth 50m|Heard I. and McDonald Is.',
 'World|Natural Earth 50m|Honduras',
 'World|Natural Earth 50m|Hong Kong',
 'World|Natural Earth 50m|Hungary',
 'World|Natural Earth 50m|Iceland',
 'World|Natural Earth 50m|India',
 'World|Natural Earth 50m|Indian Ocean Ter.',
 'World|Natural Earth 50m|Indonesia',
 'World|Natural Earth 50m|Iran',
 'World|Natural Earth 50m|Iraq',
 'World|Natural Earth 50m|Ireland',
 'World|Natural Earth 50m|Isle of Man',
 'World|Natural Earth 50m|Israel',
 'World|Natural Earth 50m|Italy',
 'World|Natural Earth 50m|Jamaica',
 'World|Natural Earth 50m|Japan',
 'World|Natural Earth 50m|Jersey',
 'World|Natural Earth 50m|Jordan',
 'World|Natural Earth 50m|Kazakhstan',
 'World|Natural Earth 50m|Kenya',
 'World|Natural Earth 50m|Kiribati',
 'World|Natural Earth 50m|Kosovo',
 'World|Natural Earth 50m|Kuwait',
 'World|Natural Earth 50m|Kyrgyzstan',
 'World|Natural Earth 50m|Laos',
 'World|Natural Earth 50m|Latvia',
 'World|Natural Earth 50m|Lebanon',
 'World|Natural Earth 50m|Lesotho',
 'World|Natural Earth 50m|Liberia',
 'World|Natural Earth 50m|Libya',
 'World|Natural Earth 50m|Liechtenstein',
 'World|Natural Earth 50m|Lithuania',
 'World|Natural Earth 50m|Luxembourg',
 'World|Natural Earth 50m|Macao',
 'World|Natural Earth 50m|Macedonia',
 'World|Natural Earth 50m|Madagascar',
 'World|Natural Earth 50m|Malawi',
 'World|Natural Earth 50m|Malaysia',
 'World|Natural Earth 50m|Maldives',
 'World|Natural Earth 50m|Mali',
 'World|Natural Earth 50m|Malta',
 'World|Natural Earth 50m|Marshall Is.',
 'World|Natural Earth 50m|Mauritania',
 'World|Natural Earth 50m|Mauritius',
 'World|Natural Earth 50m|Mexico',
 'World|Natural Earth 50m|Micronesia',
 'World|Natural Earth 50m|Moldova',
 'World|Natural Earth 50m|Monaco',
 'World|Natural Earth 50m|Mongolia',
 'World|Natural Earth 50m|Montenegro',
 'World|Natural Earth 50m|Montserrat',
 'World|Natural Earth 50m|Morocco',
 'World|Natural Earth 50m|Mozambique',
 'World|Natural Earth 50m|Myanmar',
 'World|Natural Earth 50m|N. Cyprus',
 'World|Natural Earth 50m|N. Mariana Is.',
 'World|Natural Earth 50m|Namibia',
 'World|Natural Earth 50m|Nauru',
 'World|Natural Earth 50m|Nepal',
 'World|Natural Earth 50m|Netherlands',
 'World|Natural Earth 50m|New Caledonia',
 'World|Natural Earth 50m|New Zealand',
 'World|Natural Earth 50m|Nicaragua',
 'World|Natural Earth 50m|Niger',
 'World|Natural Earth 50m|Nigeria',
 'World|Natural Earth 50m|Niue',
 'World|Natural Earth 50m|Norfolk Island',
 'World|Natural Earth 50m|North Korea',
 'World|Natural Earth 50m|Norway',
 'World|Natural Earth 50m|Oman',
 'World|Natural Earth 50m|Pakistan',
 'World|Natural Earth 50m|Palau',
 'World|Natural Earth 50m|Palestine',
 'World|Natural Earth 50m|Panama',
 'World|Natural Earth 50m|Papua New Guinea',
 'World|Natural Earth 50m|Paraguay',
 'World|Natural Earth 50m|Peru',
 'World|Natural Earth 50m|Philippines',
 'World|Natural Earth 50m|Pitcairn Is.',
 'World|Natural Earth 50m|Poland',
 'World|Natural Earth 50m|Portugal',
 'World|Natural Earth 50m|Puerto Rico',
 'World|Natural Earth 50m|Qatar',
 'World|Natural Earth 50m|Romania',
 'World|Natural Earth 50m|Russia',
 'World|Natural Earth 50m|Rwanda',
 'World|Natural Earth 50m|S. Geo. and the Is.',
 'World|Natural Earth 50m|S. Sudan',
 'World|Natural Earth 50m|Saint Helena',
 'World|Natural Earth 50m|Saint Lucia',
 'World|Natural Earth 50m|Samoa',
 'World|Natural Earth 50m|San Marino',
 'World|Natural Earth 50m|Saudi Arabia',
 'World|Natural Earth 50m|Senegal',
 'World|Natural Earth 50m|Serbia',
 'World|Natural Earth 50m|Seychelles',
 'World|Natural Earth 50m|Siachen Glacier',
 'World|Natural Earth 50m|Sierra Leone',
 'World|Natural Earth 50m|Singapore',
 'World|Natural Earth 50m|Sint Maarten',
 'World|Natural Earth 50m|Slovakia',
 'World|Natural Earth 50m|Slovenia',
 'World|Natural Earth 50m|Solomon Is.',
 'World|Natural Earth 50m|Somalia',
 'World|Natural Earth 50m|Somaliland',
 'World|Natural Earth 50m|South Africa',
 'World|Natural Earth 50m|South Korea',
 'World|Natural Earth 50m|Spain',
 'World|Natural Earth 50m|Sri Lanka',
 'World|Natural Earth 50m|St-Barthélemy',
 'World|Natural Earth 50m|St-Martin',
 'World|Natural Earth 50m|St. Kitts and Nevis',
 'World|Natural Earth 50m|St. Pierre and Miquelon',
 'World|Natural Earth 50m|St. Vin. and Gren.',
 'World|Natural Earth 50m|Sudan',
 'World|Natural Earth 50m|Suriname',
 'World|Natural Earth 50m|Sweden',
 'World|Natural Earth 50m|Switzerland',
 'World|Natural Earth 50m|Syria',
 'World|Natural Earth 50m|São Tomé and Principe',
 'World|Natural Earth 50m|Taiwan',
 'World|Natural Earth 50m|Tajikistan',
 'World|Natural Earth 50m|Tanzania',
 'World|Natural Earth 50m|Thailand',
 'World|Natural Earth 50m|Timor-Leste',
 'World|Natural Earth 50m|Togo',
 'World|Natural Earth 50m|Tonga',
 'World|Natural Earth 50m|Trinidad and Tobago',
 'World|Natural Earth 50m|Tunisia',
 'World|Natural Earth 50m|Turkey',
 'World|Natural Earth 50m|Turkmenistan',
 'World|Natural Earth 50m|Turks and Caicos Is.',
 'World|Natural Earth 50m|U.S. Virgin Is.',
 'World|Natural Earth 50m|Uganda',
 'World|Natural Earth 50m|Ukraine',
 'World|Natural Earth 50m|United Arab Emirates',
 'World|Natural Earth 50m|United Kingdom',
 'World|Natural Earth 50m|United States of America',
 'World|Natural Earth 50m|Uruguay',
 'World|Natural Earth 50m|Uzbekistan',
 'World|Natural Earth 50m|Vanuatu',
 'World|Natural Earth 50m|Vatican',
 'World|Natural Earth 50m|Venezuela',
 'World|Natural Earth 50m|Vietnam',
 'World|Natural Earth 50m|W. Sahara',
 'World|Natural Earth 50m|Wallis and Futuna Is.',
 'World|Natural Earth 50m|Yemen',
 'World|Natural Earth 50m|Zambia',
 'World|Natural Earth 50m|Zimbabwe',
 'World|Natural Earth 50m|eSwatini',
 'World|Natural Earth 50m|Åland',
 'World|North Atlantic Ocean',
 'World|Northern Hemisphere',
 'World|Northern Hemisphere|Land',
 'World|Northern Hemisphere|Ocean',
 'World|Southern Hemisphere',
 'World|Southern Hemisphere|Land',
 'World|Southern Hemisphere|Ocean']

User-defined masks

As a user, you can also define weights. Simply add them to netcdf_scm.WEIGHTS_FUNCTIONS_WITHOUT_AREA_WEIGHTING.WEIGHTS_FUNCTIONS_WITHOUT_AREA_WEIGHTING and then use them in your get_scm_cubes call.

WEIGHTS_FUNCTIONS_WITHOUT_AREA_WEIGHTING["custom mask"] = get_weights_for_area(
    -60, 100, -10, 330
    "Northern Atlantic area bounds"
] = get_weights_for_area(0, -80, 65, 0)
custom_weights = example.get_scm_timeseries_weights(
        "World|El Nino N3.4",
        "custom mask",
        "Northern Atlantic area bounds",