Synthetic plug-in electric vehicle charging behavior for eight U.S. regions, grounded in NHTS 2017 travel micro-data.
A reproducible, NHTS-grounded synthetic load curve for a regional EV fleet — from pip install to plot in under ten minutes.
ev-flow generates large, behaviorally realistic populations of individual plug-in EV (PEV) charging profiles. Grid-integration studies, hosting-capacity analyses, load forecasting, and managed-charging research all need vehicle-level heterogeneity — battery size, charger/EVSE power, dwell times, arrival/departure timing, plug-in propensity, seasonal energy — across thousands of vehicles, and they need it reproducibly. Real charging telemetry that captures this is scarce and privacy-restricted; the open generators that exist are mostly calibrated to European mobility surveys.
ev-flow fills the U.S.-focused, NHTS-grounded slice of that space. A deterministic nine-stage pipeline (M1–M9) carries each synthetic vehicle from 2017 National Household Travel Survey micro-data to a time-stamped charging profile: it donor-stitches survey person-days into 365-day travel calendars with a temperature-dependent winter energy uplift, samples plug-in start times from the published SPEECh K=16 Gaussian-mixture parameterization, propagates a continuous-time state-of-charge ledger with an explicit PHEV gasoline range-extension term, and rasterizes plug status to 15-minute and hourly grids. Every output is UTC-stored, timezone-aware, and bit-reproducible from a single master seed.
It is not universally better than the alternatives — it fills a specific niche. See When to use ev-flow and the feature comparison for an honest placement against emobpy, VencoPy, datafev, ACN-Sim and others.
The PyPI distribution name is ev-flow; the Python import name is pev_synth. You pip install ev-flow and then import pev_synth — the same convention as scikit-learn / sklearn. Both names refer to this one project throughout the docs.
- Eight U.S. regions —
bay_area,boston,chicago,dallas_fort_worth,la_basin,new_york_metro,seattle, plus a reference-onlyus_national. Each carries its own states/CBSAs, IANA time zone, ISO market, regional sales-mix source, and winter temperature uplift. - Residential and workplace profile types, end-to-end.
- Per-vehicle
Profileobjects with trips, plug status, charging sessions, and a continuous SoC trajectory — plus aFleetobject for aggregation and filtering. - NHTS-microdata donor stitching, not parametric sampling over aggregate statistics.
- SPEECh K=16 start-time sampler by default (Powell, Cezar & Rajagopal 2022), with weekday/weekend selection.
- Descriptive EVSE enrichment — brand and connector per vehicle (descriptive only; they do not change the effective charge rate).
- UTC-canonical storage with tz-aware query across the four active U.S. zones, DST-verified.
- Reproducible from a single master seed; deterministic per-module and per-vehicle sub-seed namespaces.
- Honest validation runner that ties every divergence from a published bound to a documented, sourced reason rather than tuning it away.
pip install ev-flowSupports Python 3.10–3.13. The wheel ships the pev_synth package and the small bundled SPEECh K=16 parameters — but not the cached fleet bundles or NHTS micro-data, which are built locally on first run (see below).
The wheel ships only the Python code; the per-region fleet caches are built from NHTS 2017 micro-data the first time you run ev-flow. Bootstrap once:
# One-time setup: write the offline sales-mix CSVs, download the NHTS 2017
# public-use file (~84 MB ORNL zip), and build the default cache. Runs the
# full M1-M9 pipeline, so budget a few minutes. Every step is idempotent.
ev-flow bootstrap
# ...or pick regions / profile types explicitly:
ev-flow bootstrap --regions bay_area la_basin --profile-types residential workplace
# Verify the environment any time (read-only diagnostics):
ev-flow doctorThe bootstrap downloads NHTS; the SPEECh K=16 parameters are already bundled in the wheel. If you keep a prebuilt data tree elsewhere, skip the bootstrap and point
PEV_SYNTH_DATA_ROOTat it instead — the expected layout is<root>/pev/processed/<region>/<profile_type>_ev_synth/. Until a cache exists,generate_profiles(...)raisesFileNotFoundErrorpointing back at this step.
Equivalent module entry points (handy in a pip install -e . dev checkout):
python -m pev_synth.nhts_loader # (a) download + process NHTS 2017
python -m pev_synth.cache_regen one --region bay_area --profile-type residential # (b) build one cacheOnce the cache exists, the library API works entirely offline:
import pev_synth as ps
ps.list_regions()
# ['bay_area', 'boston', 'chicago', 'dallas_fort_worth',
# 'la_basin', 'new_york_metro', 'seattle', 'us_national']
ps.list_profile_types()
# ['residential', 'workplace']
# Draw a 500-EV residential fleet for the Bay Area (seed makes the subset reproducible):
fleet = ps.generate_profiles('residential', n=500, region='bay_area', seed=42)
prof = fleet[0]
# Per-EV queries over a half-open window on the 2001 synthetic calendar:
plugged = prof.plug_status('2001-01-01', '2001-01-08', freq='15min') # bool Series
sessions = prof.charging_sessions('2001-06-01', '2001-06-08') # DataFrame
soc = prof.soc_trajectory('2001-06-01', '2001-06-08', freq='15min') # kWh
# Fleet-aggregate charging power (kW) — a load curve:
load_kw = fleet.aggregate_load('2001-06-01', '2001-06-08', freq='1h')By default every series/frame is indexed in UTC (the storage zone); pass tz=fleet.region.tz (or any IANA zone) for a local wall-clock index. The full ten-minute path is in the Quickstart.
ev-flow is deliberately scoped, and it fails loudly outside that scope. It does not model vehicle-to-grid / bidirectional power flow, smart-charging / managed-charging optimization (it generates the population that such algorithms consume; strategy is out of scope), fleet-depot charging (de-scoped — generate_profiles('fleet_depot', ...) raises ValueError), public / DC-fast charging, or non-U.S. geographies. The us_national region is reference-only and not materializable.
It is also honest about where it diverges from the literature. The reference bay_area residential profile rolls up to 11 PASS / 0 FAIL / 6 EXPLAINED_FAIL / 4 EXPLAINED_SKIP / 0 ERROR: each non-PASS row is a documented, sourced limitation, not a hidden bug. Most prominently, the workplace clusters are fit from a small (105-vehicle) public EVWatts cohort whose plug-in median (~12:00 local time) sits about three hours later than the literature-canonical ~09:00; the validator flags W1–W4 as EXPLAINED_FAIL, and constructing any workplace fleet emits a RuntimeWarning so it can never be silently mis-interpreted. See the Limitations discussion before relying on a single profile.
- Documentation site — homepage, methodology, and the auto-generated API reference.
- Quickstart — install, bootstrap, and reach a load curve in under ten minutes.
- Tutorials — residential aggregate load, comparing regions, save/reload a fleet.
- When to use ev-flow — a decision guide by use case and constraint, including when another tool is the better fit.
- Feature comparison — ev-flow vs emobpy, VencoPy, RAMP-mobility, datafev, ACN-Sim, and others.
- API Reference — the full
Fleet/Profile/generate_profilesand region surface.
ev-flow is grounded in public data. Two upstream notices are required:
- SPEECh Original Model (Powell, Cezar & Rajagopal, Mendeley Data, 2022) is licensed CC BY 4.0 — attribution required. ev-flow consumes a modified (pickle→JSON, reweighted) subset of its driver-group mixtures and K=16 start-time parameters. DOI 10.17632/gvk34mybtb.1.
- This product uses the U.S. Census Bureau Data API but is not endorsed or certified by the Census Bureau.
Full per-source licensing, citations, and the modification statement are in ATTRIBUTION.md (NHTS 2017, NHTS NextGen 2022, U.S. Census ACS PUMS, EPA fueleconomy.gov, EV WATTS, CVRP-CA, NYSERDA Drive Clean, Argonne, CARB EMFAC2021, NOAA, NREL).
MIT — see LICENSE. The MIT license covers the ev-flow code; the upstream data sources retain their own licenses (see ATTRIBUTION.md).
If you use ev-flow in your research, please cite it via the version-independent Zenodo concept DOI:
Travacca, Bertrand. ev-flow: synthetic plug-in electric vehicle charging data. Zenodo. https://doi.org/10.5281/zenodo.20619156
@software{travacca_ev_flow,
author = {Travacca, Bertrand},
title = {{ev-flow: synthetic plug-in electric vehicle charging data}},
publisher = {Zenodo},
doi = {10.5281/zenodo.20619156},
url = {https://doi.org/10.5281/zenodo.20619156}
}A machine-readable CITATION.cff is also provided.

