Skip to main content

Python wrapper for EPA's AERMOD air dispersion model

Project description

PyAERMOD

Tests Python 3.11+ License: MIT

Python wrapper for EPA's AERMOD atmospheric dispersion model.

PyAERMOD automates input file generation, model execution, output parsing, and result visualization — replacing manual text-file editing with a type-safe Python API.

Installation

pip install pyaermod             # core (input generation + output parsing)
pip install pyaermod[viz]        # + matplotlib/folium visualization
pip install pyaermod[geo]        # + geospatial export (GeoTIFF, Shapefile)
pip install pyaermod[gui]        # + Streamlit interactive GUI
pip install pyaermod[all]        # everything

For development:

git clone https://github.com/atmmod/pyaermod.git
cd pyaermod
pip install -e ".[dev,all]"

Quick Start

Generate AERMOD Input

from pyaermod.input_generator import (
    AERMODProject, ControlPathway, SourcePathway, ReceptorPathway,
    MeteorologyPathway, OutputPathway, PointSource, CartesianGrid,
    PollutantType, TerrainType,
)

control = ControlPathway(
    title_one="My Facility",
    pollutant_id=PollutantType.PM25,
    averaging_periods=["ANNUAL", "24"],
    terrain_type=TerrainType.FLAT,
)

sources = SourcePathway()
sources.add_source(PointSource(
    source_id="STACK1", x_coord=500.0, y_coord=500.0,
    base_elevation=10.0, stack_height=50.0, stack_temp=400.0,
    exit_velocity=15.0, stack_diameter=2.0, emission_rate=1.5,
))

receptors = ReceptorPathway()
receptors.add_cartesian_grid(CartesianGrid.from_bounds(
    x_min=0, x_max=2000, y_min=0, y_max=2000, spacing=100,
))

meteorology = MeteorologyPathway(
    surface_file="met_data.sfc", profile_file="met_data.pfl",
)
output = OutputPathway(receptor_table=True, max_table=True)

project = AERMODProject(control, sources, receptors, meteorology, output)
project.write("facility.inp")

Run AERMOD & Parse Results

from pyaermod.runner import run_aermod
from pyaermod.output_parser import parse_aermod_output

result = run_aermod("facility.inp")
results = parse_aermod_output(result.output_file)

df = results.get_concentrations("ANNUAL")
print(results.summary())

Parse POSTFILE Output

from pyaermod.postfile import read_postfile

# Auto-detects text vs binary format
post = read_postfile("postfile.out")
df = post.to_dataframe()

# Binary postfile with deposition data
dep = read_postfile("depo_post.out", has_deposition=True)
print(dep.to_dataframe()[["concentration", "dry_depo", "wet_depo"]])

Features

Source Types (10)

POINT, AREA, AREACIRC, AREAPOLY, VOLUME, LINE, RLINE, RLINEXT, BUOYLINE, OPENPIT

Advanced Modeling

  • Background concentrations — uniform, period-specific, or sector-dependent
  • Deposition — dry, wet, or combined for gas and particle emissions
  • NO2/SO2 chemistry — OLM, PVMRM, ARM2, GRSM with ozone data
  • Source groups — custom groupings with per-group PLOTFILE output
  • EVENT processing — date/receptor-specific analysis

Preprocessors

  • AERMET — meteorological data preprocessing (Stages 1-3)
  • AERMAP — terrain elevation extraction with DEM download pipeline

Analysis & Visualization

  • Output parsing to pandas DataFrames
  • POSTFILE parser for timestep-level results (text and binary formats)
  • Contour plots, interactive Folium maps, 3D surfaces, wind roses
  • Geospatial export: GeoTIFF, GeoPackage, Shapefile, GeoJSON

Validation & Automation

  • Input validation across all AERMOD pathways
  • Building downwash / BPIP integration (point, area, and volume sources)
  • Batch processing with parallel execution
  • Interactive Streamlit GUI (pyaermod-gui)

Project Structure

src/pyaermod/
    __init__.py          # Public API
    input_generator.py   # AERMOD input file generation (all source types)
    validator.py         # Configuration validation
    runner.py            # AERMOD subprocess execution
    output_parser.py     # Output file parsing
    postfile.py          # POSTFILE output parser
    visualization.py     # Matplotlib/Folium plots
    advanced_viz.py      # 3D surfaces, wind roses, animations
    aermet.py            # AERMET preprocessor wrapper
    aermap.py            # AERMAP input generation
    terrain.py           # DEM download + AERMAP pipeline
    geospatial.py        # Coordinate transforms, GIS export
    bpip.py              # Building downwash calculations
    gui.py               # Streamlit web GUI
tests/                   # 1383 tests, 98% coverage
examples/                # Example scripts and Jupyter notebooks
docs/                    # Architecture and quickstart guides

Requirements

  • Python >= 3.11
  • numpy, pandas (core)
  • AERMOD executable (free from EPA SCRAM)

Documentation

License

MIT

Disclaimer

PyAERMOD is a wrapper around AERMOD, not a reimplementation. It uses official EPA binaries for all calculations and maintains regulatory acceptance. Always validate results against EPA test cases for your specific use case.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyaermod-1.2.0.tar.gz (319.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyaermod-1.2.0-py3-none-any.whl (116.0 kB view details)

Uploaded Python 3

File details

Details for the file pyaermod-1.2.0.tar.gz.

File metadata

  • Download URL: pyaermod-1.2.0.tar.gz
  • Upload date:
  • Size: 319.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for pyaermod-1.2.0.tar.gz
Algorithm Hash digest
SHA256 6ebf32be35fbc3209ffb217bf7a1253ec372ee982160e6e84d05652628790dad
MD5 9dc8e8f4079772ca8ce23181a887a742
BLAKE2b-256 b9f9360da403719515dee418be84db4c961355e896a68df1690b67db2a17e44a

See more details on using hashes here.

File details

Details for the file pyaermod-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: pyaermod-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 116.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for pyaermod-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ab0a882145bbf60a85d71a43b801dc8617c2d3456de53a8a50e2a5b5ad972e66
MD5 a35a6c5d4d218f01914670a7fac8eba8
BLAKE2b-256 b5df8e82bbc6f9ef63cc6d8371b14cc7f8c5ab68a259845424f94bbc79bd55b5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page