agentsclimarketplace

Climate data analysis

Skill Lord1Egypt/scientific-agent-toolkit/scientific-skills/climate-data-analysis

148 ready-to-use AI agent skills for research, science, engineering, analysis & writing. Works with Claude Code, Cursor, Codex and any Agent Skills-compatible agent.

Install
npx -y skills add Lord1Egypt/scientific-agent-toolkit --skill climate-data-analysis

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Climate and Earth system data analysis using xarray, cartopy, cfgrib, and CMIP6/ERA5 datasets. Use for loading NetCDF/GRIB climate data, computing climatologies, spatial aggregation, anomaly detection, bias correction, and publication-quality climate maps. Best for atmospheric, oceanic, and land surface data analysis.

The file declares its own license as MIT license. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

7.5 KB, as published. Nobody here has run it

Climate Data Analysis

Overview

Climate data analysis involves working with large multi-dimensional gridded datasets from reanalyses (ERA5, MERRA-2), climate model outputs (CMIP6), observational datasets (GPCC, GHCN), and satellite products. This skill covers the complete workflow from data access to publication-quality visualization.

When to Use This Skill

  • Loading and processing NetCDF or GRIB climate datasets
  • Computing climatologies, anomalies, and trends
  • Spatial and temporal aggregation of climate variables
  • Creating climate maps with proper projections (cartopy)
  • Accessing CMIP6 model outputs and ERA5 reanalysis data
  • Bias correction of climate model outputs
  • Calculating climate indices (ENSO, NAO, drought indices)
  • Downscaling or regridding climate data

Quick Start

Loading Climate Data with xarray

import xarray as xr
import numpy as np

# Load a NetCDF file
ds = xr.open_dataset("era5_temperature_2020.nc")
print(ds)

# Select a variable and time slice
t2m = ds["t2m"]  # 2m temperature in Kelvin
t2m_celsius = t2m - 273.15  # Convert to Celsius

# Compute annual mean
annual_mean = t2m_celsius.groupby("time.year").mean("time")

# Spatial subset (Europe)
europe = t2m_celsius.sel(
    latitude=slice(75, 35),
    longitude=slice(-15, 45)
)
print(f"Shape: {europe.shape}")
print(f"Time range: {europe.time.values[0]} to {europe.time.values[-1]}")

Climate Climatology and Anomalies

import xarray as xr
import numpy as np

ds = xr.open_dataset("monthly_temperature.nc")
temp = ds["temperature"]

# Compute 30-year climatology (1991-2020 standard)
clim = temp.sel(time=slice("1991", "2020")).groupby("time.month").mean("time")

# Compute anomalies
anomalies = temp.groupby("time.month") - clim

# Rolling trend (10-year)
trend = anomalies.rolling(time=120, center=True).mean()

print(f"Climatology shape: {clim.shape}")
print(f"Anomaly mean: {float(anomalies.mean()):.4f}")

ERA5 Data Access via CDS API

import cdsapi

client = cdsapi.Client()

# Download ERA5 monthly mean 2m temperature
client.retrieve(
    "reanalysis-era5-single-levels-monthly-means",
    {
        "product_type": "monthly_averaged_reanalysis",
        "variable": ["2m_temperature", "total_precipitation"],
        "year": [str(y) for y in range(2000, 2024)],
        "month": [f"{m:02d}" for m in range(1, 13)],
        "time": "00:00",
        "format": "netcdf",
        "area": [90, -180, -90, 180],  # Global
    },
    "era5_monthly_2000_2023.nc",
)

Climate Maps with Cartopy

import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature

ds = xr.open_dataset("temperature_anomaly.nc")
anomaly = ds["t2m_anomaly"].isel(time=0)

fig, ax = plt.subplots(
    figsize=(14, 7),
    subplot_kw={"projection": ccrs.Robinson()}
)

# Plot data
im = anomaly.plot(
    ax=ax,
    transform=ccrs.PlateCarree(),
    cmap="RdBu_r",
    robust=True,
    cbar_kwargs={"label": "Temperature Anomaly (°C)", "shrink": 0.8},
    add_colorbar=True,
)

# Add geographic features
ax.add_feature(cfeature.COASTLINE, linewidth=0.5)
ax.add_feature(cfeature.BORDERS, linewidth=0.3, linestyle="--")
ax.add_feature(cfeature.LAND, facecolor="lightgray", alpha=0.3)
ax.gridlines(draw_labels=True, dms=True, x_inline=False, y_inline=False)

ax.set_title("Global Temperature Anomaly", fontsize=14, fontweight="bold")
plt.tight_layout()
plt.savefig("climate_map.png", dpi=200, bbox_inches="tight")
print("Climate map saved.")

CMIP6 Data Access via Pangeo

import intake
import xarray as xr

# Access CMIP6 catalog
catalog = intake.open_esm_datastore(
    "https://storage.googleapis.com/cmip6/pangeo-cmip6.json"
)

# Search for specific model output
cat_subset = catalog.search(
    experiment_id=["historical", "ssp585"],
    table_id="Amon",
    variable_id="tas",
    member_id="r1i1p1f1",
    source_id="CESM2",
)

# Load datasets
dsets = cat_subset.to_dataset_dict(zarr_kwargs={"consolidated": True})
print(list(dsets.keys()))

# Historical temperature
hist = dsets["CMIP.NCAR.CESM2.historical.Amon.gn"]
ssp585 = dsets["ScenarioMIP.NCAR.CESM2.ssp585.Amon.gn"]

# Global mean temperature
global_mean_hist = hist["tas"].mean(["lat", "lon"])
global_mean_ssp585 = ssp585["tas"].mean(["lat", "lon"])

Spatial Statistics

import xarray as xr
import numpy as np

def area_weighted_mean(da: xr.DataArray) -> xr.DataArray:
    """Compute area-weighted spatial mean (accounts for grid cell size)."""
    weights = np.cos(np.deg2rad(da.lat))
    weights.name = "weights"
    return da.weighted(weights).mean(["lat", "lon"])

ds = xr.open_dataset("global_temperature.nc")
temp = ds["temperature"]

# Area-weighted global mean temperature
global_temp = area_weighted_mean(temp)
print(f"Global mean temperature: {float(global_temp.mean()):.2f} K")

# Trend calculation
from scipy import stats
time_num = np.arange(len(global_temp))
slope, intercept, r, p, se = stats.linregress(time_num, global_temp.values)
print(f"Trend: {slope*10:.3f} K/decade (p={p:.4f})")

Climate Indices

import xarray as xr
import numpy as np

def calculate_nino34(sst: xr.DataArray) -> xr.DataArray:
    """Calculate Niño 3.4 index (ENSO indicator)."""
    # Niño 3.4 region: 5°S-5°N, 170°W-120°W
    nino34_region = sst.sel(
        lat=slice(-5, 5),
        lon=slice(190, 240)  # 170W-120W in 0-360 coords
    )
    # Area-weighted mean
    weights = np.cos(np.deg2rad(nino34_region.lat))
    nino34 = nino34_region.weighted(weights).mean(["lat", "lon"])
    # Remove climatology
    clim = nino34.groupby("time.month").mean("time")
    return nino34.groupby("time.month") - clim

def calculate_drought_index(precip: xr.DataArray, window: int = 12) -> xr.DataArray:
    """Simplified SPI (Standardized Precipitation Index)."""
    rolling_precip = precip.rolling(time=window).sum()
    mean = rolling_precip.groupby("time.month").mean("time")
    std = rolling_precip.groupby("time.month").std("time")
    spi = (rolling_precip.groupby("time.month") - mean) / std
    return spi

Regridding with xesmf

import xarray as xr
import xesmf as xe

# Regrid from coarse to fine grid (or vice versa)
ds_coarse = xr.open_dataset("cmip6_model_1deg.nc")
ds_fine = xr.open_dataset("observations_0.25deg.nc")

# Create regridder
regridder = xe.Regridder(ds_coarse, ds_fine, "bilinear")

# Apply regridding
ds_regridded = regridder(ds_coarse)
print(f"Regridded shape: {ds_regridded['tas'].shape}")

Key Datasets

DatasetVariableResolutionAccess
ERA5All atmospheric vars0.25°, hourlyCDS API
CMIP6Climate model outputs1°, monthlyPangeo/ESGF
GPCCPrecipitation0.25°, monthlyFTP
HadCRUT5Temperature5°, monthlyUK Met Office
MODISLand surface500m, dailyNASA

Dependencies

pip install xarray netCDF4 cartopy matplotlib scipy
pip install cdsapi  # ERA5 access
pip install intake intake-esm  # CMIP6 catalog
pip install xesmf  # Regridding
conda install -c conda-forge cfgrib eccodes  # GRIB support

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.