Quick Start Guide

Get started with SPI and SPEI calculations in 5 minutes!

Setup Python Path

Before using the package, add the src folder to your Python path:

import sys
sys.path.insert(0, 'src')  # Or use absolute path

Basic Usage

Calculate SPI

Calculate the Standard Precipitation Index (SPI) for your precipitation data:

import sys
sys.path.insert(0, 'src')

import xarray as xr
from indices import spi, save_index_to_netcdf

# Load your precipitation data
ds = xr.open_dataset('your_precip_data.nc')
precip = ds['precip']  # or 'precipitation', 'prcp', 'pr'

# Calculate SPI-12 (12-month scale)
spi_12 = spi(
    precip,
    scale=12,
    periodicity='monthly',
    calibration_start_year=1991,
    calibration_end_year=2020
)

# Save results
save_index_to_netcdf(spi_12, 'spi_12_output.nc')

Calculate SPEI

Calculate the Standardized Precipitation Evapotranspiration Index (SPEI):

from indices import spei

# Load precipitation and temperature
precip = ds['precip']
temp = ds['temperature']
lat = ds['lat']

# Calculate SPEI-12 (auto-calculates PET from temperature)
spei_12 = spei(
    precip,
    temperature=temp,
    latitude=lat,
    scale=12,
    periodicity='monthly',
    calibration_start_year=1991,
    calibration_end_year=2020
)

# With Pearson III distribution (recommended for SPEI)
spei_12_p3 = spei(
    precip,
    temperature=temp,
    latitude=lat,
    scale=12,
    distribution='pearson3'
)

save_index_to_netcdf(spei_12_p3, 'spei_pearson3_12_output.nc')
TipTemperature-based PET

The spei() function can automatically calculate PET when you provide temperature data:

  • Thornthwaite (default): Requires only mean temperature. Simple and widely used.
  • Hargreaves: Requires Tmin/Tmax data. Better for arid/semi-arid regions.
# Thornthwaite (default)
spei_12 = spei(precip, temperature=temp, latitude=lat, scale=12)

# Hargreaves (requires Tmin/Tmax)
spei_12 = spei(precip, temperature=temp, latitude=lat, scale=12,
               pet_method='hargreaves', temp_min=tmin, temp_max=tmax)

If you have pre-computed PET values, use pet=your_pet_data instead of temperature=.

TipDistribution Selection

By default, all functions use the Gamma distribution. You can choose from five supported distributions via the distribution parameter:

  • 'gamma' — Default, standard for SPI (McKee et al. 1993)
  • 'pearson3' — Recommended for SPEI (Vicente-Serrano et al. 2010)
  • 'log_logistic' — Alternative for SPEI (original R SPEI package)
  • 'gev' — For extreme value analysis
  • 'gen_logistic' — European dry/wet indices

See the Probability Distributions page for detailed guidance.

Multi-Scale Calculation

Calculate multiple time scales at once for efficiency:

from indices import spi_multi_scale

# Calculate SPI for multiple time scales at once
spi_multi = spi_multi_scale(
    precip,
    scales=[1, 3, 6, 12],
    periodicity='monthly',
    calibration_start_year=1991,
    calibration_end_year=2020
)

# Access individual scales
spi_1 = spi_multi['spi_gamma_1_month']
spi_3 = spi_multi['spi_gamma_3_month']
spi_12 = spi_multi['spi_gamma_12_month']
NotePerformance Tip

Multi-scale calculation is more efficient than calculating each scale separately, especially for large datasets.

Save and Reuse Parameters

Speed up repeated calculations by saving and reusing fitted distribution parameters:

from indices import save_fitting_params, load_fitting_params

# Calculate SPI and save parameters
spi_12, params = spi(precip, scale=12, return_params=True)

# Save parameters for future use
save_fitting_params(
    params,
    'spi_params.nc',
    scale=12,
    periodicity='monthly',
    index_type='spi'
)

# Later: Load and reuse parameters (much faster!)
params = load_fitting_params('spi_params.nc', scale=12, periodicity='monthly')
spi_12_fast = spi(new_precip, scale=12, fitting_params=params)

Customizing Output Metadata

By default, output NetCDF files include minimal metadata (source, CF conventions). You can customize the metadata attributes in two ways:

Modify DEFAULT_METADATA at the start of your script. All subsequent outputs will use these values:

from config import DEFAULT_METADATA

# Set your organization's metadata
DEFAULT_METADATA['institution'] = 'My University, Department of Geography'
DEFAULT_METADATA['source'] = 'precip-index package v2026.1'
DEFAULT_METADATA['references'] = 'McKee et al. (1993)'
DEFAULT_METADATA['comment'] = 'Drought monitoring project'

# All subsequent outputs will include these attributes
spi_12 = spi(precip, scale=12)

Pass global_attrs to override metadata for specific outputs:

spi_ds = spi_multi_scale(
    precip,
    scales=[3, 12],
    global_attrs={
        'institution': 'ACME Research Lab',
        'project': 'Regional Drought Monitor',
    }
)

# Also works with save_fitting_params, spi_global, spei_global, etc.
save_fitting_params(
    params, 'spi_params.nc',
    scale=12, periodicity='monthly', index_type='spi',
    global_attrs={'institution': 'My Organization'}
)
TipAvailable Metadata Fields

The default metadata fields are: institution, source, Conventions, references, and comment. You can also add any custom fields via global_attrs (e.g., project, contact, license).

Climate Extremes Event Analysis

Identify and analyze complete extreme events using run theory:

from runtheory import identify_events
from visualization import plot_events

# Identify dry (drought) events (negative threshold)
spi_location = spi_12.isel(lat=50, lon=100)
dry_events = identify_events(spi_location, threshold=-1.2, min_duration=3)

print(f"Found {len(dry_events)} dry events")
print(dry_events[['start_date', 'end_date', 'duration', 'magnitude', 'peak']])

# Visualize events
plot_events(spi_location, dry_events, threshold=-1.2)
# Identify wet events (positive threshold) - same function!
wet_events = identify_events(spi_location, threshold=+1.2, min_duration=3)

print(f"Found {len(wet_events)} wet events")
plot_events(spi_location, wet_events, threshold=+1.2)
from runtheory import calculate_period_statistics

# Calculate gridded statistics for a time period
stats = calculate_period_statistics(
    spi_12,
    threshold=-1.2,
    start_year=2020,
    end_year=2024
)

# Plot number of events per grid cell
stats.num_events.plot(title='Number of Dry/Wet Events 2020-2024')
ImportantBidirectional Analysis

The same functions work for both drought (negative threshold) and wet events (positive threshold). This unified approach makes analysis consistent and straightforward.

Data Requirements

Your input data must be NetCDF with (time, lat, lon) dimensions (any order — auto-transposed). SPI needs precipitation; SPEI also needs temperature or pre-computed PET. A 30-year calibration period (default 1991–2020) is recommended.

TipFull specification

See Data Model & Outputs for the complete input contract, output schemas, calibration conventions, and zero/NaN handling details.

Understanding the Output

SPI/SPEI Classification

Value Range Category Percentile band (approx.) Interpretation
≤ -2.00 Exceptionally Dry 0–2.3% Exceptional drought
-2.00 to -1.50 Extremely Dry 2.3–6.7% Severe drought
-1.50 to -1.20 Severely Dry 6.7–11.5% Severe drought
-1.20 to -0.70 Moderately Dry 11.5–24.2% Moderate drought
-0.70 to -0.50 Abnormally Dry 24.2–30.9% Below normal
-0.50 to +0.50 Near Normal 30.9–69.1% Normal conditions
+0.50 to +0.70 Abnormally Moist 69.1–75.8% Above normal
+0.70 to +1.20 Moderately Moist 75.8–88.5% Moderately wet
+1.20 to +1.50 Very Moist 88.5–93.3% Very wet conditions
+1.50 to +2.00 Extremely Moist 93.3–97.7% Extremely wet conditions
≥ +2.00 Exceptionally Moist 97.7–100% Extreme flooding risk

Percentile bands are approximate (standard normal) and provided for intuitive frequency interpretation.

Time Scales

Scale Application Use Case
1-month Meteorological Short-term precipitation deficits
3-month Agricultural Seasonal crop stress
6-month Agricultural/Hydrological Medium-term water resources
12-month Hydrological Long-term water supply
24-month Socio-economic Multi-year water planning

Common Issues

WarningIssue: “ModuleNotFoundError: No module named ‘indices’”

Solution: Make sure to add the src directory to Python path:

import sys
sys.path.insert(0, 'src')
WarningIssue: All NaN output

Possible causes:

  • Calibration period doesn’t overlap with data
  • All zero or negative precipitation values
  • Check: precip.min(), precip.max(), data year range
WarningIssue: “ValueError: cannot reshape array”

Solution: This was a bug in earlier versions, now fixed! The code automatically handles any dimension order.

Run the Test Script

Test with the included example data:

python tests/run_all_tests.py

This will:

  1. Load TerraClimate Bali data from input/ folder
  2. Calculate SPI-3 and multi-scale SPI
  3. Calculate SPEI with temperature
  4. Test run theory functions
  5. Display statistics and validation

Expected runtime: ~30 seconds

Learn More

📓 Jupyter Notebooks

Interactive tutorials with real data

View Tutorials

📖 User Guide

Detailed methodology and usage

Read Guide

🔧 API Reference

Complete function documentation

API Docs

Next Steps

Now that you know the basics:

  1. Try the tutorials - Work through interactive examples with real climate data
  2. Read the methodology - Understand SPI, SPEI, and run theory
  3. Explore visualizations - Create publication-quality plots
  4. Use your own data - Apply the package to your research

Support

Need help?

  1. Check the Tutorials for step-by-step examples
  2. Review the User Guide for detailed explanations
  3. See test results for validation examples
  4. Open an issue on GitHub

See Also

Ready to dive deeper? Try the SPI Tutorial next!

Back to top