Maximum Covariance Analysis#

Maximum Covariance Analysis (MCA) between two data sets.

# Load packages and data:
import numpy as np
import xarray as xr
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
from cartopy.crs import Orthographic, PlateCarree
from cartopy.feature import LAND

from xeofs.models import MCA

Create 2 different DataArrays

t2m = xr.tutorial.load_dataset("air_temperature")["air"]
da1 = t2m.isel(lon=slice(0, 26))
da2 = t2m.isel(lon=slice(27, None))

Perform MCA

mca = MCA(n_modes=20, standardize=False, use_coslat=True)
mca.fit(da1, da2, dim="time")
<xeofs.models.mca.MCA object at 0x7f01747daa50>

Get singular vectors, projections (PCs), homogeneous and heterogeneous patterns:

singular_vectors = mca.components()
scores = mca.scores()
hom_pats, pvals_hom = mca.homogeneous_patterns()
het_pats, pvals_het = mca.heterogeneous_patterns()

When two fields are expected, the output of the above methods is a list of length 2, with the first and second entry containing the relevant object for X and Y. For example, the p-values obtained from the two-sided t-test for the homogeneous patterns of X are:

pvals_hom[0]
<xarray.DataArray 'pvalues_of_left_homogeneous_patterns' (mode: 20, lat: 25,
                                                          lon: 26)>
array([[[7.29374897e-298, 4.92157472e-268, 8.32382290e-265, ...,
         1.08681083e-108, 1.03639765e-164, 0.00000000e+000],
        [0.00000000e+000, 1.10991037e-316, 1.20740718e-261, ...,
         4.10518390e-131, 1.44361817e-128, 2.12644639e-154],
        [0.00000000e+000, 0.00000000e+000, 3.62777187e-317, ...,
         7.98234852e-039, 2.30423459e-094, 2.21447015e-303],
        ...,
        [0.00000000e+000, 0.00000000e+000, 0.00000000e+000, ...,
         0.00000000e+000, 0.00000000e+000, 0.00000000e+000],
        [0.00000000e+000, 0.00000000e+000, 0.00000000e+000, ...,
         0.00000000e+000, 0.00000000e+000, 0.00000000e+000],
        [0.00000000e+000, 0.00000000e+000, 0.00000000e+000, ...,
         0.00000000e+000, 0.00000000e+000, 0.00000000e+000]],

       [[3.53356464e-053, 2.16458187e-064, 1.82082352e-072, ...,
         2.73963215e-061, 1.91557069e-001, 1.78821911e-051],
        [1.09082456e-048, 9.63033598e-054, 5.03588837e-061, ...,
         5.32308100e-062, 3.17748175e-139, 4.93155255e-125],
        [2.28500864e-026, 6.67730087e-023, 1.31657526e-042, ...,
         3.45643640e-301, 5.93676048e-211, 6.80890371e-056],
...
        [6.68028323e-015, 6.36799636e-016, 1.40424635e-015, ...,
         7.79519418e-001, 5.47948179e-001, 3.94369444e-001],
        [1.60502590e-010, 2.56625354e-010, 1.28102262e-009, ...,
         2.29172525e-001, 1.46246437e-001, 1.06877108e-001],
        [1.32442878e-009, 3.66374656e-009, 1.85914222e-008, ...,
         1.67860641e-001, 1.50368398e-001, 1.54500266e-001]],

       [[3.52336556e-001, 1.68719893e-002, 1.89032329e-002, ...,
         7.85325588e-001, 2.77656062e-004, 2.09278514e-009],
        [3.51835129e-001, 2.03858184e-001, 1.77920685e-001, ...,
         1.67769352e-003, 1.75517410e-004, 3.62760486e-006],
        [4.94662972e-001, 3.67637823e-001, 1.12698398e-001, ...,
         1.02161213e-007, 7.09256483e-005, 3.77172316e-004],
        ...,
        [4.02700721e-019, 1.70640543e-018, 2.01380734e-017, ...,
         6.53881051e-001, 6.06515118e-001, 5.74031976e-001],
        [7.98658654e-007, 2.85676775e-006, 1.07423123e-005, ...,
         8.18013734e-001, 9.27700927e-001, 9.60593627e-001],
        [3.43962237e-002, 6.48273766e-002, 1.22432687e-001, ...,
         8.68261063e-002, 1.68867366e-001, 2.89714726e-001]]])
Coordinates:
  * lat      (lat) float32 15.0 17.5 20.0 22.5 25.0 ... 65.0 67.5 70.0 72.5 75.0
  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 255.0 257.5 260.0 262.5
  * mode     (mode) int64 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Attributes: (12/14)
    model:         MCA
    software:      xeofs
    version:       1.2.0
    date:          2023-10-29 13:29:43
    n_modes:       20
    center:        True
    ...            ...
    n_pca_modes:   None
    compute:       True
    sample_name:   sample
    feature_name:  feature
    solver:        auto
    random_state:  None


Create a mask to identifiy where p-values are below 0.05

hom_mask = [values < 0.05 for values in pvals_hom]
het_mask = [values < 0.05 for values in pvals_het]

Plot some relevant quantities of mode 2.

lonlats = [
    np.meshgrid(pvals_hom[0].lon.values, pvals_hom[0].lat.values),
    np.meshgrid(pvals_hom[1].lon.values, pvals_hom[1].lat.values),
]
proj = [
    Orthographic(central_latitude=30, central_longitude=-120),
    Orthographic(central_latitude=30, central_longitude=-60),
]
kwargs1 = {"cmap": "BrBG", "vmin": -0.05, "vmax": 0.05, "transform": PlateCarree()}
kwargs2 = {"cmap": "RdBu", "vmin": -1, "vmax": 1, "transform": PlateCarree()}

mode = 2

fig = plt.figure(figsize=(7, 14))
gs = GridSpec(5, 2)
ax1 = [fig.add_subplot(gs[0, i], projection=proj[i]) for i in range(2)]
ax2 = [fig.add_subplot(gs[1, i], projection=proj[i]) for i in range(2)]
ax3 = [fig.add_subplot(gs[2, i], projection=proj[i]) for i in range(2)]
ax4 = [fig.add_subplot(gs[3, i]) for i in range(2)]

for i, a in enumerate(ax1):
    singular_vectors[i].sel(mode=mode).plot(ax=a, **kwargs1)

for i, a in enumerate(ax2):
    hom_pats[i].sel(mode=mode).plot(ax=a, **kwargs2)
    a.scatter(
        lonlats[i][0],
        lonlats[i][1],
        hom_mask[i].sel(mode=mode).values * 0.5,
        color="k",
        alpha=0.5,
        transform=PlateCarree(),
    )
for i, a in enumerate(ax3):
    het_pats[i].sel(mode=mode).plot(ax=a, **kwargs2)
    a.scatter(
        lonlats[i][0],
        lonlats[i][1],
        het_mask[i].sel(mode=mode).values * 0.5,
        color="k",
        alpha=0.5,
        transform=PlateCarree(),
    )

for i, a in enumerate(ax4):
    scores[i].sel(mode=mode).plot(ax=a)
    a.set_xlabel("")


for a in np.ravel([ax1, ax2, ax3]):
    a.coastlines(color=".5")
    a.add_feature(LAND)

plt.tight_layout()
plt.savefig("mca.jpg")
mode = 2, mode = 2, mode = 2, mode = 2, mode = 2, mode = 2, mode = 2, mode = 2

Total running time of the script: (0 minutes 4.349 seconds)

Gallery generated by Sphinx-Gallery