Lightweight Python package for creating synoptic-style meteorological charts
For CLI-first usage (recommended), see CLI_README.md.
SynopticCharts is a modern Python package that automates the creation of synoptic meteorological charts from numerical weather prediction model data. It combines automated data retrieval, meteorological analysis, and publication-quality visualization—so your attention stays on the atmosphere, not on file formats.
- Automated Model Data Download: Seamlessly retrieve forecast data from GFS and ECMWF models via herbie-data
- MSLP Analysis: Generate mean sea level pressure contours with automatic surface feature detection (High/Low markers)
- Multi-Type Precipitation Visualization: Display rain, snow, freezing rain, and sleet with type-specific color schemes
- 1000-500mb Thickness Analysis: Create atmospheric thickness charts for temperature structure analysis
- Professional Meteorological Styling: Industry-standard map projections, contour intervals, and annotations
- Video Generation: Create animated forecast sequences from multiple time steps (requires optional video dependencies)
# Not yet published on PyPI.
# Install directly from GitHub:
pip install "git+https://github.com/krober10nd/SynopticCharts.git"Clone the repository and install in editable mode with development tools:
git clone https://github.com/krober10nd/SynopticCharts.git
cd SynopticCharts
pip install -e ".[dev]"For MP4 generation capabilities:
pip install "git+https://github.com/krober10nd/SynopticCharts.git#egg=synoptic-charts[video]"- Python 3.10 or higher
- All dependencies are automatically installed via pip
Create a single synoptic chart with minimal code:
from synoptic_charts import create_chart
from datetime import datetime
# Generate a 24-hour GFS forecast chart
create_chart(
model="GFS",
forecast_cycle=datetime(2024, 1, 15, 0), # 2024-01-15 00Z cycle
lead_time=24, # 24-hour forecast
output_path="chart.png"
)Create an animated forecast sequence:
from synoptic_charts import BatchChartGenerator, create_video_from_batch
from datetime import datetime
# Initialize batch generator
batch = BatchChartGenerator(
model="GFS",
forecast_cycle=datetime(2024, 1, 15, 0),
output_dir="frames",
parallel=True, # Enable parallel processing
max_workers=4
)
# Generate frames for 0-48 hour forecast (3-hour intervals)
batch_result = batch.generate_forecast_sequence(
start_hour=0,
end_hour=48,
interval=3
)
# Create video from frames
create_video_from_batch(
batch_result=batch_result,
output_path="forecast.mp4",
fps=10
)
# Optionally cleanup frames after video creation
# batch.cleanup_frames()SynopticCharts includes a comprehensive CLI:
# Generate a single chart
synoptic-charts chart GFS 2024011500 24 --output chart.png
# Generate batch frames
synoptic-charts batch GFS 2024011500 --start 0 --end 48 --interval 3 --output frames
# Create video from frames
synoptic-charts video frames/frame_%03d.png --output forecast.mp4 --fps 10
# Combined workflow (batch + video)
synoptic-charts animate GFS 2024011500 --start 0 --end 48 --interval 3 --output animation.mp4See the examples directory for more detailed usage examples.
Customize chart appearance and behavior using the Config class:
from synoptic_charts import Config
# Create custom configuration
config = Config(
default_dpi=300, # High resolution output
figure_width=20.0,
figure_height=15.0,
mslp_contour_interval=2.0, # 2 hPa intervals for fine detail
thickness_contour_interval=3.0 # 30 meter intervals
)
# Save configuration for reuse
config.save_to_file("my_config.yaml")
# Load and use saved configuration
config = Config.load_from_file("my_config.yaml")
create_chart(..., config=config)See the configuration guide for comprehensive documentation of all parameters.
Create charts for specific geographic regions:
from synoptic_charts import create_chart, REGIONS
from datetime import datetime
# Use built-in CONUS region (default)
create_chart(
model="GFS",
forecast_cycle=datetime(2024, 1, 15, 0),
lead_time=24,
output_path="conus.png",
region="CONUS" # This is the default
)
# Define custom Southeast region and add to REGIONS
southeast_region = {
"name": "Southeast US",
"extent": [-90.0, -75.0, 25.0, 37.0], # [W, E, S, N]
"projection_params": {
"central_longitude": -82.5,
"central_latitude": 31.0,
"standard_parallels": (27.0, 35.0),
},
"figure_size": (12, 10) # width, height in inches
}
# Add to REGIONS dictionary for reuse
REGIONS["SOUTHEAST"] = southeast_region
create_chart(
model="GFS",
forecast_cycle=datetime(2024, 1, 15, 0),
lead_time=24,
output_path="southeast.png",
region="SOUTHEAST"
)Use pre-downloaded data instead of fetching from servers:
from synoptic_charts import ModelDownloader, create_chart_from_data, Config
from datetime import datetime, timedelta
def get_recent_forecast_cycle():
now = datetime.utcnow()
cycle_hour = (now.hour // 6) * 6
return datetime(now.year, now.month, now.day, cycle_hour) - timedelta(hours=6)
# Download data once
forecast_cycle = get_recent_forecast_cycle()
lead_time = 24
downloader = ModelDownloader(
model_name="GFS",
init_time=forecast_cycle,
forecast_hour=lead_time,
config=Config(),
)
data_dict = downloader.fetch_all_data()
# Create multiple charts with different settings without re-downloading
create_chart_from_data(
data_dict=data_dict,
model_name="GFS",
init_time=forecast_cycle,
valid_time=forecast_cycle + timedelta(hours=lead_time),
lead_time=lead_time,
output_path="chart.png"
)Check available lead times before generating charts:
from synoptic_charts import get_available_lead_times
# Get valid forecast hours for GFS
lead_times = get_available_lead_times("GFS")
print(f"GFS provides forecasts: {lead_times}")
# Output: [0, 3, 6, 9, ..., 384]
# Validate your requested lead time
requested = 72
if requested in lead_times:
create_chart(model="GFS", lead_time=requested, ...)
else:
print(f"Lead time {requested} not available for GFS")Generate a complete synoptic chart from model data.
create_chart(
model: str,
forecast_cycle: datetime,
lead_time: int,
region: str = "CONUS",
output_path: Optional[str] = None,
config: Optional[Config] = None
) -> Union[str, Tuple[matplotlib.figure.Figure, matplotlib.axes.Axes]]Parameters:
model: Model name ("GFS" or "ECMWF")forecast_cycle: Forecast initialization timelead_time: Forecast hour (0-384 for GFS, 0-240 for ECMWF)region: Region name from REGIONS dictionary (default: "CONUS")output_path: Path to save chart (PNG, PDF, or SVG); if None, returns (fig, ax)config: Configuration object (default: Config())
Returns:
- If
output_pathprovided: path to saved chart file - If
output_pathis None: tuple of (figure, axes) for interactive use
Create chart from pre-loaded data dictionary.
create_chart_from_data(
data_dict: Dict[str, Any],
model_name: str,
init_time: datetime,
valid_time: datetime,
lead_time: int,
region: str = "CONUS",
output_path: Optional[str] = None,
config: Optional[Config] = None
) -> Union[str, Tuple[matplotlib.figure.Figure, matplotlib.axes.Axes]]Parameters:
data_dict: Dictionary from ModelDownloader.fetch_all_data() with keys: 'mslp', 'precip_rate', 'precip_categorical', 'geopotential_heights'model_name: Model name for annotation (e.g., "GFS", "ECMWF")init_time: Model initialization datetimevalid_time: Valid datetime for forecastlead_time: Forecast hour for annotationregion: Region name from REGIONS dictionary (default: "CONUS")output_path: Path to save chart; if None, returns (fig, ax)config: Configuration object (default: Config())
Returns: Same as create_chart()
Get list of valid forecast hours for a model.
get_available_lead_times(model: str) -> List[int]Returns: List of available forecast hours
Generate multiple chart frames for video creation.
from synoptic_charts import BatchChartGenerator
batch = BatchChartGenerator(
model: str,
forecast_cycle: datetime,
output_dir: str = "frames",
frame_pattern: str = "frame_%03d.png",
region: Optional[dict] = None,
config: Optional[Config] = None,
parallel: bool = False,
max_workers: int = 4,
show_progress: bool = True
)Methods:
generate_frames(lead_times: List[int]): Generate frames for specific forecast hoursgenerate_forecast_sequence(start_hour, end_hour, interval): Generate evenly-spaced framescleanup_frames(keep_latest: int = 0): Remove generated frames
Create MP4 video from batch-generated frames.
from synoptic_charts import create_video_from_batch
create_video_from_batch(
batch_result: Dict[str, Any],
output_path: str,
fps: int = 10,
codec: str = "libx264",
crf: int = 23,
preset: str = "medium"
)Parameters:
batch_result: Dictionary returned by BatchChartGenerator.generate_frames() or generate_forecast_sequence()output_path: Output video file pathfps: Frames per second (default: 10)codec: Video codec (default: "libx264")crf: Constant Rate Factor for quality (18=high, 28=low)preset: Encoding preset ("fast", "medium", "slow")
Note: To remove frames after video creation, call batch.cleanup_frames() after this function
Lower-level video creation from frame files.
from synoptic_charts import VideoGenerator
video_gen = VideoGenerator(
frame_dir: str = "frames",
frame_pattern: str = "frame_%03d.png"
)
video_gen.create_video(
output_path: str,
fps: int = 10,
codec: str = "libx264",
crf: int = 23,
preset: str = "medium"
)Configuration dataclass for customizing chart appearance.
from synoptic_charts import Config
config = Config(
default_dpi: int = 150,
figure_width: float = 16.0,
figure_height: float = 12.0,
cache_dir: str = "~/.synoptic_charts_cache",
trace_threshold: float = 0.01,
light_threshold: float = 0.1,
moderate_threshold: float = 0.25,
heavy_threshold: float = 0.5,
mslp_contour_interval: float = 4.0,
thickness_contour_interval: float = 6.0
)Methods:
save_to_file(path: str): Save configuration to YAML/JSONload_from_file(path: str): Load configuration from file
Custom exception hierarchy for better error handling:
from synoptic_charts import (
SynopticChartsError, # Base exception
DataFetchError, # Data download failures
RenderError, # Chart rendering issues
VideoCreationError, # Video encoding problems
InvalidParameterError # Invalid configuration/parameters
)Install with CLI support:
# Not yet published on PyPI.
pip install "git+https://github.com/krober10nd/SynopticCharts.git"synoptic-charts chart <model> <cycle> <lead_time> [options]
# Example
synoptic-charts chart GFS 2024011500 24 --output chart.png --region NORTHEASTsynoptic-charts batch <model> <cycle> [options]
# Example
synoptic-charts batch GFS 2024011500 --start 0 --end 48 --interval 3 --output frames --parallelsynoptic-charts video <frame_pattern> [options]
# Example
synoptic-charts video "frames/frame_%03d.png" --output video.mp4 --fps 10 --cleanupsynoptic-charts animate <model> <cycle> [options]
# Example
synoptic-charts animate GFS 2024011500 --start 0 --end 120 --interval 6 --output forecast.mp4All commands support:
-v, --verbose: Increase output verbosity-vv: Debug output--config <file>: Load configuration from file
Typical synoptic chart outputs include:
- MSLP contours (black lines, labeled in hPa)
- High/Low pressure centers (marked with H/L and pressure values)
- Precipitation areas (colored by type: rain=green, snow=blue, freezing rain=magenta, ice pellets=purple)
- Precipitation amounts (shaded by intensity)
- 1000-500mb thickness (red dashed contours, with 540 dam line bold)
- Geographic features (coastlines, state/country borders)
- Title and timestamp (model, initialization time, valid time)
See the examples directory for sample outputs and code.
- herbie-data (≥2024.0.0): Automated model data download from NOAA and ECMWF sources
- matplotlib (≥3.7.0): Publication-quality plotting and visualization
- cartopy (≥0.22.0): Geospatial data processing and map projections
- metpy (≥1.5.0): Meteorological calculations and unit handling
- xarray (≥2023.0.0): Multidimensional labeled array operations
- numpy (≥1.24.0): Numerical computing foundation
- scipy (≥1.10.0): Scientific computing and feature detection algorithms
- cfgrib (≥0.9.10): GRIB2 file format support
If you see errors like "data file not found" or DataFetchError:
- Use a recent forecast cycle (model data is typically only kept for ~10 days).
- If you choose the most recent cycle, wait ~2–3 hours after cycle time.
- Verify your network connection (and any proxy/firewall rules).
- Try a different lead time (e.g.,
lead_time=12orlead_time=24).
Video creation requires the ffmpeg binary.
- macOS:
brew install ffmpeg - Ubuntu/Debian:
sudo apt-get install ffmpeg - Windows: Download from https://ffmpeg.org/download.html
Verify installation:
ffmpeg -versionIf you see errors originating from Herbie (inventory/search/xarray failures):
- Verify
herbie-datais installed and up to date. - Clear the cache directory (default:
~/.synoptic_charts_cache) if you suspect a corrupted download. - Search strings can change across model products; try a different cycle/lead time.
If the chart renders but appears empty or missing layers:
- The selected cycle/lead time may not include all variables needed.
- Try a different cycle or lead time.
- For small custom regions, ensure your region
extentandprojection_paramsare reasonable.
This project is licensed under the MIT License. See the LICENSE file for details.
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests through the GitHub repository.
This package builds upon the excellent work of:
- herbie-data: Brian Blaylock's powerful interface for weather model data access
- MetPy: Unidata's comprehensive meteorological analysis toolkit
- Cartopy: The cartographic library for Python by the UK Met Office
- matplotlib: The foundational visualization library for Python
Special thanks to the broader scientific Python ecosystem (NumPy, SciPy, xarray) that makes projects like this possible.