Rotated Maximum Covariance Analysis#

Rotated Maximum Covariance Analysis (MCA) between two data sets.

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

import xeofs as xe

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 = xe.cross.MCA(n_modes=20, standardize=False, use_coslat=True)
mca.fit(da1, da2, dim="time")
<xeofs.cross.mca.MCA object at 0x7e858f640e50>

Apply Varimax-rotation to MCA solution

rot = xe.cross.MCARotator(n_modes=10)
rot.fit(mca)
<xeofs.cross.mca_rotator.MCARotator object at 0x7e858f643bd0>

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

singular_vectors = rot.components()
scores = rot.scores()
hom_pats, pvals_hom = rot.homogeneous_patterns()
het_pats, pvals_het = rot.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: 10, lat: 25,
                                                          lon: 26)>
1.562e-89 1.552e-68 7.788e-62 2.969e-52 ... 0.002105 0.005704 0.01526 0.03629
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
Attributes: (9)


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("rotated_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.585 seconds)

Gallery generated by Sphinx-Gallery