4.1 Air Masses

An air mass is a large body of air with relatively uniform temperature and humidity characteristics, acquired from its source region. Air masses are classified by their source and modification.

Air Mass Classification

Continental Polar (cP)

Cold, dry. Source: Siberia, Canada

Winter: T ~ -30°C, Td ~ -35°C

Maritime Polar (mP)

Cool, moist. Source: N. Pacific, N. Atlantic

T ~ 5°C, Td ~ 2°C

Continental Tropical (cT)

Hot, dry. Source: Sahara, SW deserts

T ~ 40°C, Td ~ 5°C

Maritime Tropical (mT)

Warm, humid. Source: Gulf of Mexico, tropics

T ~ 25°C, Td ~ 22°C

Source Region Requirements

  • • Large, uniform surface (ocean or flat land)
  • • Light winds (stagnant high pressure)
  • • Several days of residence time
  • • Clear distinction from surrounding air

Python: Air Mass Properties

#!/usr/bin/env python3
"""
air_masses.py - Air mass classification and properties

Run: python3 air_masses.py
Requires: pip install numpy matplotlib
"""
import numpy as np
import matplotlib.pyplot as plt

# Air mass properties (T in °C, Td in °C, typical values)
air_masses = {
    'cA': {'T': -50, 'Td': -55, 'name': 'Continental Arctic', 'color': 'darkblue'},
    'cP': {'T': -20, 'Td': -30, 'name': 'Continental Polar', 'color': 'blue'},
    'mP': {'T': 5, 'Td': 2, 'name': 'Maritime Polar', 'color': 'cyan'},
    'cT': {'T': 40, 'Td': 5, 'name': 'Continental Tropical', 'color': 'red'},
    'mT': {'T': 25, 'Td': 22, 'name': 'Maritime Tropical', 'color': 'orange'},
    'mE': {'T': 27, 'Td': 25, 'name': 'Maritime Equatorial', 'color': 'green'},
}

def saturation_vapor_pressure(T):
    """Tetens formula (hPa)"""
    return 6.11 * np.exp(17.27 * T / (T + 237.3))

def relative_humidity(T, Td):
    """Calculate RH from T and Td"""
    e = saturation_vapor_pressure(Td)
    es = saturation_vapor_pressure(T)
    return 100 * e / es

# Plot
fig, axes = plt.subplots(1, 2, figsize=(14, 6))

# T-Td diagram
ax1 = axes[0]
for abbrev, props in air_masses.items():
    T, Td = props['T'], props['Td']
    RH = relative_humidity(T, Td)
    ax1.scatter(T, Td, s=200, c=props['color'], label=f"{abbrev}: {props['name']}", edgecolor='white', linewidth=2)
    ax1.annotate(abbrev, (T+2, Td+2), fontsize=10, fontweight='bold')

# Add diagonal lines of constant RH
T_range = np.linspace(-50, 45, 100)
for rh in [20, 40, 60, 80, 100]:
    Td_line = 237.3 * np.log(rh/100 * saturation_vapor_pressure(T_range) / 6.11) / (17.27 - np.log(rh/100 * saturation_vapor_pressure(T_range) / 6.11))
    valid = ~np.isnan(Td_line) & (Td_line > -60) & (Td_line < T_range)
    ax1.plot(T_range[valid], Td_line[valid], 'gray', linestyle='--', alpha=0.5)
    # Label
    idx = len(T_range)//2
    if valid[idx]:
        ax1.text(T_range[idx], Td_line[idx]-3, f'{rh}%', fontsize=8, color='gray')

ax1.set_xlabel('Temperature (°C)', fontsize=12)
ax1.set_ylabel('Dew Point (°C)', fontsize=12)
ax1.set_title('Air Mass Classification (T vs Td)', fontsize=14)
ax1.legend(loc='upper left', fontsize=8)
ax1.grid(True, alpha=0.3)
ax1.set_xlim(-55, 50)
ax1.set_ylim(-60, 30)

# Bar chart of properties
ax2 = axes[1]
x = np.arange(len(air_masses))
width = 0.35

temps = [props['T'] for props in air_masses.values()]
dews = [props['Td'] for props in air_masses.values()]
labels = list(air_masses.keys())
colors = [props['color'] for props in air_masses.values()]

bars1 = ax2.bar(x - width/2, temps, width, label='Temperature', color=colors, alpha=0.7)
bars2 = ax2.bar(x + width/2, dews, width, label='Dew Point', color=colors, alpha=0.4, hatch='//')

ax2.set_xlabel('Air Mass Type', fontsize=12)
ax2.set_ylabel('Temperature (°C)', fontsize=12)
ax2.set_title('Air Mass Temperature & Dew Point', fontsize=14)
ax2.set_xticks(x)
ax2.set_xticklabels(labels)
ax2.legend()
ax2.axhline(y=0, color='gray', linestyle='-', alpha=0.3)
ax2.grid(True, alpha=0.3, axis='y')

plt.tight_layout()
plt.savefig('air_masses.png', dpi=150, bbox_inches='tight')
plt.show()

print("Air Mass Properties:")
print("-" * 60)
print(f"{'Type':<6} {'Name':<25} {'T(°C)':<8} {'Td(°C)':<8} {'RH(%)':<8}")
print("-" * 60)
for abbrev, props in air_masses.items():
    RH = relative_humidity(props['T'], props['Td'])
    print(f"{abbrev:<6} {props['name']:<25} {props['T']:<8} {props['Td']:<8} {RH:.0f}")