Python wrapper for EPA's AERMOD air dispersion model
Project description
PyAERMOD
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyaermod-1.7.0.tar.gz.
File metadata
- Download URL: pyaermod-1.7.0.tar.gz
- Upload date:
- Size: 479.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b9d37ac0d904bd37fda7be5222bac5d7d6f5682b28548a4727036aeb3330f3c2
|
|
| MD5 |
5841cec62553381835bb13f81452eacc
|
|
| BLAKE2b-256 |
874c578198e6803d9ace72317028d399c3f737711772dee3bc859d23cd2ad2e0
|
Provenance
The following attestation bundles were made for pyaermod-1.7.0.tar.gz:
Publisher:
publish.yml on atmmod/pyaermod
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyaermod-1.7.0.tar.gz -
Subject digest:
b9d37ac0d904bd37fda7be5222bac5d7d6f5682b28548a4727036aeb3330f3c2 - Sigstore transparency entry: 1438080164
- Sigstore integration time:
-
Permalink:
atmmod/pyaermod@b01243c8057739692774704d969952ecc54c2dee -
Branch / Tag:
refs/tags/v1.7.0 - Owner: https://github.com/atmmod
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b01243c8057739692774704d969952ecc54c2dee -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyaermod-1.7.0-py3-none-any.whl.
File metadata
- Download URL: pyaermod-1.7.0-py3-none-any.whl
- Upload date:
- Size: 198.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f59ecdb4590fd8c898bd815265b6225a2f1c33204e6991d16e85534d518a272e
|
|
| MD5 |
105a4f34728d2f277f1b11c654fc7bc5
|
|
| BLAKE2b-256 |
208cfbf26c088d3f7e86f963c571dfbcbf1d8ce0a98b716c744dcacc7d938428
|
Provenance
The following attestation bundles were made for pyaermod-1.7.0-py3-none-any.whl:
Publisher:
publish.yml on atmmod/pyaermod
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyaermod-1.7.0-py3-none-any.whl -
Subject digest:
f59ecdb4590fd8c898bd815265b6225a2f1c33204e6991d16e85534d518a272e - Sigstore transparency entry: 1438080182
- Sigstore integration time:
-
Permalink:
atmmod/pyaermod@b01243c8057739692774704d969952ecc54c2dee -
Branch / Tag:
refs/tags/v1.7.0 - Owner: https://github.com/atmmod
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b01243c8057739692774704d969952ecc54c2dee -
Trigger Event:
release
-
Statement type: