mobev 0.2.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mobev-0.4.0/PKG-INFO +231 -0
- mobev-0.4.0/README.md +206 -0
- {mobev-0.2.0 → mobev-0.4.0}/mobev/__init__.py +24 -12
- {mobev-0.2.0 → mobev-0.4.0}/mobev/_version.py +1 -1
- mobev-0.4.0/mobev/aggregation/__init__.py +5 -0
- mobev-0.4.0/mobev/aggregation/results_aggregator.py +591 -0
- mobev-0.4.0/mobev/charging/__init__.py +6 -0
- mobev-0.4.0/mobev/charging/charging_simulator.py +976 -0
- mobev-0.4.0/mobev/charging/decision_engine.py +741 -0
- mobev-0.4.0/mobev/charging/events.py +439 -0
- mobev-0.4.0/mobev/charging/profiles.py +141 -0
- mobev-0.4.0/mobev/charging/sessions.py +238 -0
- mobev-0.4.0/mobev/cli/__init__.py +1 -0
- mobev-0.4.0/mobev/cli/run_mobev.py +205 -0
- mobev-0.4.0/mobev/config/__init__.py +39 -0
- mobev-0.4.0/mobev/config/config.py +296 -0
- mobev-0.4.0/mobev/config/defaults.py +88 -0
- mobev-0.4.0/mobev/config/load.py +274 -0
- mobev-0.4.0/mobev/config/models.py +207 -0
- mobev-0.4.0/mobev/config/random.py +48 -0
- mobev-0.4.0/mobev/config/serialization.py +39 -0
- mobev-0.4.0/mobev/config/validation.py +306 -0
- mobev-0.4.0/mobev/pipeline.py +325 -0
- mobev-0.4.0/mobev/plot/__init__.py +15 -0
- mobev-0.4.0/mobev/plot/axes.py +29 -0
- mobev-0.4.0/mobev/plot/output.py +45 -0
- mobev-0.4.0/mobev/plot/plot.py +273 -0
- mobev-0.4.0/mobev/plot/profile_data.py +118 -0
- mobev-0.4.0/mobev/plot/profile_render.py +147 -0
- mobev-0.4.0/mobev/plot/tariff.py +47 -0
- mobev-0.4.0/mobev/plot/time.py +67 -0
- mobev-0.4.0/mobev/plot/trip_map_data.py +224 -0
- mobev-0.4.0/mobev/plot/trip_map_html.py +139 -0
- mobev-0.4.0/mobev/plot/weather.py +75 -0
- mobev-0.4.0/mobev/results/__init__.py +19 -0
- mobev-0.4.0/mobev/results/aggregated_results.py +797 -0
- mobev-0.4.0/mobev/results/charging_simulation.py +261 -0
- mobev-0.4.0/mobev/results/common.py +254 -0
- mobev-0.4.0/mobev/results/indicators.py +350 -0
- mobev-0.4.0/mobev/results/metadata.py +404 -0
- mobev-0.4.0/mobev/results/output.py +226 -0
- mobev-0.4.0/mobev/results/prepared_trips.py +288 -0
- mobev-0.4.0/mobev/results/scenario_inputs.py +426 -0
- mobev-0.4.0/mobev/results/schemas.py +194 -0
- mobev-0.4.0/mobev/results/simulation_results.py +98 -0
- {mobev-0.2.0 → mobev-0.4.0}/mobev/scenario/__init__.py +2 -1
- mobev-0.4.0/mobev/scenario/fleet.py +122 -0
- mobev-0.4.0/mobev/scenario/parking.py +358 -0
- mobev-0.4.0/mobev/scenario/scenario_builder.py +638 -0
- mobev-0.4.0/mobev/scenario/stations.py +85 -0
- mobev-0.4.0/mobev/scenario/tariffs.py +241 -0
- mobev-0.4.0/mobev/scenario/weather.py +130 -0
- mobev-0.4.0/mobev/trips/boundaries.py +343 -0
- mobev-0.4.0/mobev/trips/chains.py +279 -0
- mobev-0.4.0/mobev/trips/distances.py +162 -0
- mobev-0.4.0/mobev/trips/source.py +428 -0
- mobev-0.4.0/mobev/trips/trip_preparer.py +452 -0
- {mobev-0.2.0 → mobev-0.4.0}/mobev/utils/logger.py +33 -10
- mobev-0.4.0/mobev.egg-info/PKG-INFO +231 -0
- mobev-0.4.0/mobev.egg-info/SOURCES.txt +93 -0
- mobev-0.4.0/mobev.egg-info/entry_points.txt +2 -0
- {mobev-0.2.0 → mobev-0.4.0}/mobev.egg-info/requires.txt +1 -0
- {mobev-0.2.0 → mobev-0.4.0}/pyproject.toml +10 -4
- mobev-0.4.0/tests/test_aggregated_results_plotting.py +54 -0
- mobev-0.4.0/tests/test_charging_decision.py +458 -0
- mobev-0.4.0/tests/test_charging_simulator.py +574 -0
- mobev-0.4.0/tests/test_cli.py +153 -0
- mobev-0.4.0/tests/test_config.py +468 -0
- mobev-0.4.0/tests/test_logger.py +20 -0
- mobev-0.4.0/tests/test_metadata.py +112 -0
- mobev-0.4.0/tests/test_output.py +131 -0
- mobev-0.4.0/tests/test_pipeline.py +309 -0
- mobev-0.4.0/tests/test_pipeline_api.py +198 -0
- mobev-0.4.0/tests/test_plot_export.py +66 -0
- mobev-0.4.0/tests/test_random.py +38 -0
- mobev-0.4.0/tests/test_results.py +277 -0
- mobev-0.4.0/tests/test_results_aggregator.py +493 -0
- mobev-0.4.0/tests/test_results_indicators.py +234 -0
- mobev-0.4.0/tests/test_scenario_builder.py +258 -0
- mobev-0.4.0/tests/test_tariff_builder.py +358 -0
- mobev-0.4.0/tests/test_tariff_plotting.py +68 -0
- mobev-0.4.0/tests/test_trip_boundaries.py +471 -0
- mobev-0.4.0/tests/test_trip_chains.py +61 -0
- mobev-0.4.0/tests/test_trip_distances.py +115 -0
- {mobev-0.2.0 → mobev-0.4.0}/tests/test_trip_plotting.py +56 -67
- mobev-0.4.0/tests/test_trip_preparer.py +225 -0
- mobev-0.4.0/tests/test_trip_source.py +116 -0
- mobev-0.4.0/tests/test_weather.py +149 -0
- mobev-0.4.0/tests/test_weather_demand.py +138 -0
- mobev-0.4.0/tests/test_weather_plotting.py +83 -0
- mobev-0.2.0/PKG-INFO +0 -191
- mobev-0.2.0/README.md +0 -167
- mobev-0.2.0/mobev/charging/__init__.py +0 -5
- mobev-0.2.0/mobev/charging/charging_simulator.py +0 -605
- mobev-0.2.0/mobev/charging/tariffs.py +0 -451
- mobev-0.2.0/mobev/core/config.py +0 -900
- mobev-0.2.0/mobev/core/pipeline.py +0 -206
- mobev-0.2.0/mobev/plotting/__init__.py +0 -6
- mobev-0.2.0/mobev/plotting/api.py +0 -250
- mobev-0.2.0/mobev/plotting/data.py +0 -122
- mobev-0.2.0/mobev/plotting/render.py +0 -83
- mobev-0.2.0/mobev/plotting/tariff.py +0 -137
- mobev-0.2.0/mobev/plotting/trips.py +0 -376
- mobev-0.2.0/mobev/profiles/__init__.py +0 -5
- mobev-0.2.0/mobev/profiles/profile_aggregator.py +0 -382
- mobev-0.2.0/mobev/results/__init__.py +0 -54
- mobev-0.2.0/mobev/results/aggregated_profiles.py +0 -118
- mobev-0.2.0/mobev/results/charging_simulation.py +0 -133
- mobev-0.2.0/mobev/results/common.py +0 -281
- mobev-0.2.0/mobev/results/factories.py +0 -87
- mobev-0.2.0/mobev/results/prepared_trips.py +0 -91
- mobev-0.2.0/mobev/results/results_indicators.py +0 -132
- mobev-0.2.0/mobev/results/scenario_inputs.py +0 -219
- mobev-0.2.0/mobev/results/simulation_results.py +0 -48
- mobev-0.2.0/mobev/scenario/scenario_builder.py +0 -401
- mobev-0.2.0/mobev/trips/trip_preparer.py +0 -656
- mobev-0.2.0/mobev/utils/metadata.py +0 -132
- mobev-0.2.0/mobev.egg-info/PKG-INFO +0 -191
- mobev-0.2.0/mobev.egg-info/SOURCES.txt +0 -52
- mobev-0.2.0/tests/test_aggregated_profile_plotting.py +0 -136
- mobev-0.2.0/tests/test_charging_simulator.py +0 -149
- mobev-0.2.0/tests/test_config.py +0 -93
- mobev-0.2.0/tests/test_pipeline.py +0 -154
- mobev-0.2.0/tests/test_pipeline_api.py +0 -121
- mobev-0.2.0/tests/test_profile_aggregator.py +0 -235
- mobev-0.2.0/tests/test_results.py +0 -99
- mobev-0.2.0/tests/test_results_indicators.py +0 -116
- mobev-0.2.0/tests/test_scenario_builder.py +0 -78
- mobev-0.2.0/tests/test_tariff_pipeline.py +0 -36
- mobev-0.2.0/tests/test_trip_pipeline.py +0 -64
- mobev-0.2.0/tests/test_unit_boundaries.py +0 -73
- mobev-0.2.0/tests/test_utils.py +0 -310
- {mobev-0.2.0 → mobev-0.4.0}/LICENSE +0 -0
- {mobev-0.2.0 → mobev-0.4.0}/mobev/trips/__init__.py +0 -0
- {mobev-0.2.0 → mobev-0.4.0}/mobev.egg-info/dependency_links.txt +0 -0
- {mobev-0.2.0 → mobev-0.4.0}/mobev.egg-info/top_level.txt +0 -0
- {mobev-0.2.0 → mobev-0.4.0}/setup.cfg +0 -0
mobev-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mobev
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: MobEV: mobility-based, geolocalized EV charging-demand model.
|
|
5
|
+
Author-email: Yoann Chiche <yoann.chiche@minesparis.psl.eu>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Repository, https://git.persee.minesparis.psl.eu/planeterr/mobev
|
|
8
|
+
Project-URL: Documentation, https://pages.persee.minesparis.psl.eu/planeterr/mobev/
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.13
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: pandas
|
|
15
|
+
Requires-Dist: numpy
|
|
16
|
+
Requires-Dist: geopandas
|
|
17
|
+
Requires-Dist: pyproj
|
|
18
|
+
Requires-Dist: shapely>=2
|
|
19
|
+
Requires-Dist: polars
|
|
20
|
+
Requires-Dist: PyYAML
|
|
21
|
+
Requires-Dist: matplotlib
|
|
22
|
+
Requires-Dist: pyarrow
|
|
23
|
+
Requires-Dist: colorlog
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# MobEV
|
|
27
|
+
|
|
28
|
+
<p align="left">
|
|
29
|
+
<a href="https://pages.persee.minesparis.psl.eu/planeterr/mobev/">
|
|
30
|
+
<img src="https://pages.persee.minesparis.psl.eu/planeterr/mobev/_static/logo.png" alt="MobEV logo" width="220">
|
|
31
|
+
</a>
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
[](https://www.python.org/)
|
|
35
|
+
[](https://pypi.org/project/mobev/)
|
|
36
|
+
[](https://docs.astral.sh/uv/)
|
|
37
|
+
|
|
38
|
+
MobEV is a mobility-based, geolocalized electric-vehicle (EV) charging-demand
|
|
39
|
+
model. It turns weekly geolocated car trips into charging sessions and demand
|
|
40
|
+
profiles for distribution-network studies. MobEV samples an EV fleet and
|
|
41
|
+
charging access, simulates battery state of charge and charging decisions, and
|
|
42
|
+
reports demand at the configured timestep.
|
|
43
|
+
|
|
44
|
+
MobEV requires Python 3.13 or newer. Install the published package with:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
python -m pip install mobev
|
|
48
|
+
# or
|
|
49
|
+
uv add mobev
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
[Read the full documentation](https://pages.persee.minesparis.psl.eu/planeterr/mobev/).
|
|
53
|
+
|
|
54
|
+
## How the pipeline works
|
|
55
|
+
|
|
56
|
+
The main pipeline runs three stages in order:
|
|
57
|
+
|
|
58
|
+
1. **Prepare trips:** validate and expand weekday and weekend trip data across
|
|
59
|
+
the configured simulation dates.
|
|
60
|
+
2. **Build the scenario:** sample EV ownership and vehicle attributes, assign
|
|
61
|
+
parking and charging opportunities, and prepare tariffs and optional weather.
|
|
62
|
+
3. **Simulate charging:** process trips and parking chronologically to produce
|
|
63
|
+
battery state, charging sessions, and timestep charging profiles.
|
|
64
|
+
|
|
65
|
+
In Python, `pipeline.run()` returns the results from those stages. Aggregation
|
|
66
|
+
is a separate analysis step: it groups the detailed charging profiles by a
|
|
67
|
+
chosen population or location attribute and sums active charging power at each
|
|
68
|
+
timestep. The default `total` aggregate gives the combined load profile;
|
|
69
|
+
`location_type` and `charging_power` aggregates let you inspect subsets.
|
|
70
|
+
|
|
71
|
+
## Inputs and formats
|
|
72
|
+
|
|
73
|
+
### Configuration file
|
|
74
|
+
|
|
75
|
+
The simulation configuration is a YAML file. It defines the simulation dates
|
|
76
|
+
and timestep, fleet and battery behavior, charging rules, tariffs, and
|
|
77
|
+
locations. Relative tariff paths resolve from the YAML file. See the
|
|
78
|
+
[configuration reference](https://pages.persee.minesparis.psl.eu/planeterr/mobev/configuration.html).
|
|
79
|
+
|
|
80
|
+
A minimal configuration with a flat tariff looks like this:
|
|
81
|
+
|
|
82
|
+
```yaml
|
|
83
|
+
simulation:
|
|
84
|
+
start_date: 2024-01-01
|
|
85
|
+
end_date: 2024-01-07
|
|
86
|
+
charging:
|
|
87
|
+
target_soc: 0.9
|
|
88
|
+
minimum_parking_time_minutes: 15
|
|
89
|
+
charging_setup_duration_minutes: 0
|
|
90
|
+
range_anxiety:
|
|
91
|
+
type: normal
|
|
92
|
+
mean: 0.5
|
|
93
|
+
std: 0.15
|
|
94
|
+
min: 0.1
|
|
95
|
+
max: 0.9
|
|
96
|
+
tariff:
|
|
97
|
+
unit: EUR/kWh
|
|
98
|
+
flat_tariff: 0.30
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Other settings use their documented defaults. For the complete template and
|
|
102
|
+
all parameters, see the [configuration reference](https://pages.persee.minesparis.psl.eu/planeterr/mobev/configuration.html).
|
|
103
|
+
|
|
104
|
+
### Trip files
|
|
105
|
+
|
|
106
|
+
Pass a directory containing `weekday_trips.gpkg` and `weekend_trips.gpkg`.
|
|
107
|
+
Each GeoPackage needs a declared CRS, line geometry, and the fields
|
|
108
|
+
`person_id`, `trip_index`, `preceding_activity_index`,
|
|
109
|
+
`following_activity_index`, `departure_time`, `arrival_time`,
|
|
110
|
+
`preceding_purpose`, `following_purpose`, `is_first`, `is_last`, and `mode`.
|
|
111
|
+
Times are seconds since source-day midnight; only trimmed, case-insensitive
|
|
112
|
+
`car` rows are retained. See the [trip input schema](https://pages.persee.minesparis.psl.eu/planeterr/mobev/inputs.html#trip-inputs).
|
|
113
|
+
|
|
114
|
+
### Tariff files (optional)
|
|
115
|
+
|
|
116
|
+
Configure one or more CSV files under `tariff.files`. Each file has a zero-based
|
|
117
|
+
contiguous integer positional index and exactly one numeric `price` or
|
|
118
|
+
`price_eur_kwh` column in EUR/kWh. Without tariff files, MobEV uses the
|
|
119
|
+
configured flat tariff. Relative paths resolve from the configuration file.
|
|
120
|
+
See [tariff inputs](https://pages.persee.minesparis.psl.eu/planeterr/mobev/inputs.html#tariff-inputs).
|
|
121
|
+
|
|
122
|
+
### Weather file (optional)
|
|
123
|
+
|
|
124
|
+
For `battery.consumption_mode: temperature`, pass a separate CSV or Parquet
|
|
125
|
+
file containing `datetime` and numeric `air_temperature` values in °C.
|
|
126
|
+
Timestamps are normalized to UTC, and every hour in the simulation horizon
|
|
127
|
+
needs coverage. See [weather inputs](https://pages.persee.minesparis.psl.eu/planeterr/mobev/inputs.html#weather-inputs)
|
|
128
|
+
and [battery consumption](https://pages.persee.minesparis.psl.eu/planeterr/mobev/battery-consumption.html).
|
|
129
|
+
|
|
130
|
+
Pass the trip directory, YAML configuration, and weather file separately. The
|
|
131
|
+
[input guide](https://pages.persee.minesparis.psl.eu/planeterr/mobev/inputs.html)
|
|
132
|
+
describes field requirements, validation, and supported behavior.
|
|
133
|
+
|
|
134
|
+
## Run from Python
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from mobev import SimulationPipeline
|
|
138
|
+
|
|
139
|
+
pipeline = SimulationPipeline.from_yaml(
|
|
140
|
+
config_path="config/config.yaml",
|
|
141
|
+
trip_source_dir="data/input/trips/TRIP_FOLDER",
|
|
142
|
+
)
|
|
143
|
+
result = pipeline.run()
|
|
144
|
+
|
|
145
|
+
# Detailed timestep-level charging demand
|
|
146
|
+
print(result.charging_simulation.charging_profiles_df.head())
|
|
147
|
+
|
|
148
|
+
# Combined demand profile (aggregation is separate from run())
|
|
149
|
+
total = pipeline.aggregate(by="total")
|
|
150
|
+
print(total.aggregated_profiles_df.head())
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The default `battery.consumption_mode` is `none`; `season` applies configured
|
|
154
|
+
seasonal factors. For temperature-based consumption, set the mode to
|
|
155
|
+
`temperature` and pass weather separately:
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
pipeline = SimulationPipeline.from_yaml(
|
|
159
|
+
config_path="config/config.yaml",
|
|
160
|
+
trip_source_dir="data/input/trips/TRIP_FOLDER",
|
|
161
|
+
weather_file="data/input/weather.csv",
|
|
162
|
+
)
|
|
163
|
+
result = pipeline.run()
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Run from the command line
|
|
167
|
+
|
|
168
|
+
The installed `mobev` command writes stage tables as Parquet, indicator tables
|
|
169
|
+
as CSV, a log file, and (by default) metadata and analysis plots.
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
mobev \
|
|
173
|
+
--trips-dir data/input/trips/TRIP_FOLDER \
|
|
174
|
+
--output-dir output \
|
|
175
|
+
--config config/config.yaml
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
For temperature-based consumption, also pass the separate weather file:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
mobev \
|
|
182
|
+
--trips-dir data/input/trips/TRIP_FOLDER \
|
|
183
|
+
--output-dir output \
|
|
184
|
+
--config config/config.yaml \
|
|
185
|
+
--weather data/input/weather.csv
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`--trips-dir` and `--output-dir` are required. `--config` defaults to
|
|
189
|
+
`config/config.yaml`; `--save-metadata` and `--analyze-results` default to
|
|
190
|
+
`true`. Use `--max-profiles` to limit plotted vehicle and location groups and
|
|
191
|
+
`--weekday` to add plots for a chosen weekday. See all [CLI options and output
|
|
192
|
+
details](https://pages.persee.minesparis.psl.eu/planeterr/mobev/workflow.html#command-line-runner).
|
|
193
|
+
|
|
194
|
+
## Aggregate and plot results
|
|
195
|
+
|
|
196
|
+
Aggregation operates on a completed run and returns a separate result. For
|
|
197
|
+
example, aggregate charging by location type or by nominal charger power:
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
by_location_type = pipeline.aggregate(by="location_type")
|
|
201
|
+
by_charging_power = pipeline.aggregate(
|
|
202
|
+
by="charging_power", charging_powers=[7.4]
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
by_location_type.plot(category="location_type", save_path="by_type.png")
|
|
206
|
+
by_charging_power.plot(category="charging_power_kw", save_path="by_power.png")
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
These category plots show how the load profile is distributed across location
|
|
210
|
+
types and charger power levels:
|
|
211
|
+
|
|
212
|
+

|
|
213
|
+
|
|
214
|
+

|
|
215
|
+
|
|
216
|
+
See the [visualization guide](https://pages.persee.minesparis.psl.eu/planeterr/mobev/visualization.html)
|
|
217
|
+
for aggregation modes, filters, sampling, indicators, and plotting options.
|
|
218
|
+
|
|
219
|
+
## Documentation and project links
|
|
220
|
+
|
|
221
|
+
- [Full documentation](https://pages.persee.minesparis.psl.eu/planeterr/mobev/)
|
|
222
|
+
- [Input formats](https://pages.persee.minesparis.psl.eu/planeterr/mobev/inputs.html)
|
|
223
|
+
- [Configuration reference](https://pages.persee.minesparis.psl.eu/planeterr/mobev/configuration.html)
|
|
224
|
+
- [Charging decision algorithm](https://pages.persee.minesparis.psl.eu/planeterr/mobev/charging-algorithm.html)
|
|
225
|
+
- [Results reference](https://pages.persee.minesparis.psl.eu/planeterr/mobev/results.html)
|
|
226
|
+
- [Changelog](https://pages.persee.minesparis.psl.eu/planeterr/mobev/changelog.html)
|
|
227
|
+
- [Contributing](https://pages.persee.minesparis.psl.eu/planeterr/mobev/contribute.html)
|
|
228
|
+
- [API reference](https://pages.persee.minesparis.psl.eu/planeterr/mobev/api/)
|
|
229
|
+
|
|
230
|
+
Build the docs from a checkout with `uv sync --group docs` followed by
|
|
231
|
+
`make -C docs html`.
|
mobev-0.4.0/README.md
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# MobEV
|
|
2
|
+
|
|
3
|
+
<p align="left">
|
|
4
|
+
<a href="https://pages.persee.minesparis.psl.eu/planeterr/mobev/">
|
|
5
|
+
<img src="https://pages.persee.minesparis.psl.eu/planeterr/mobev/_static/logo.png" alt="MobEV logo" width="220">
|
|
6
|
+
</a>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
[](https://www.python.org/)
|
|
10
|
+
[](https://pypi.org/project/mobev/)
|
|
11
|
+
[](https://docs.astral.sh/uv/)
|
|
12
|
+
|
|
13
|
+
MobEV is a mobility-based, geolocalized electric-vehicle (EV) charging-demand
|
|
14
|
+
model. It turns weekly geolocated car trips into charging sessions and demand
|
|
15
|
+
profiles for distribution-network studies. MobEV samples an EV fleet and
|
|
16
|
+
charging access, simulates battery state of charge and charging decisions, and
|
|
17
|
+
reports demand at the configured timestep.
|
|
18
|
+
|
|
19
|
+
MobEV requires Python 3.13 or newer. Install the published package with:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
python -m pip install mobev
|
|
23
|
+
# or
|
|
24
|
+
uv add mobev
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
[Read the full documentation](https://pages.persee.minesparis.psl.eu/planeterr/mobev/).
|
|
28
|
+
|
|
29
|
+
## How the pipeline works
|
|
30
|
+
|
|
31
|
+
The main pipeline runs three stages in order:
|
|
32
|
+
|
|
33
|
+
1. **Prepare trips:** validate and expand weekday and weekend trip data across
|
|
34
|
+
the configured simulation dates.
|
|
35
|
+
2. **Build the scenario:** sample EV ownership and vehicle attributes, assign
|
|
36
|
+
parking and charging opportunities, and prepare tariffs and optional weather.
|
|
37
|
+
3. **Simulate charging:** process trips and parking chronologically to produce
|
|
38
|
+
battery state, charging sessions, and timestep charging profiles.
|
|
39
|
+
|
|
40
|
+
In Python, `pipeline.run()` returns the results from those stages. Aggregation
|
|
41
|
+
is a separate analysis step: it groups the detailed charging profiles by a
|
|
42
|
+
chosen population or location attribute and sums active charging power at each
|
|
43
|
+
timestep. The default `total` aggregate gives the combined load profile;
|
|
44
|
+
`location_type` and `charging_power` aggregates let you inspect subsets.
|
|
45
|
+
|
|
46
|
+
## Inputs and formats
|
|
47
|
+
|
|
48
|
+
### Configuration file
|
|
49
|
+
|
|
50
|
+
The simulation configuration is a YAML file. It defines the simulation dates
|
|
51
|
+
and timestep, fleet and battery behavior, charging rules, tariffs, and
|
|
52
|
+
locations. Relative tariff paths resolve from the YAML file. See the
|
|
53
|
+
[configuration reference](https://pages.persee.minesparis.psl.eu/planeterr/mobev/configuration.html).
|
|
54
|
+
|
|
55
|
+
A minimal configuration with a flat tariff looks like this:
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
simulation:
|
|
59
|
+
start_date: 2024-01-01
|
|
60
|
+
end_date: 2024-01-07
|
|
61
|
+
charging:
|
|
62
|
+
target_soc: 0.9
|
|
63
|
+
minimum_parking_time_minutes: 15
|
|
64
|
+
charging_setup_duration_minutes: 0
|
|
65
|
+
range_anxiety:
|
|
66
|
+
type: normal
|
|
67
|
+
mean: 0.5
|
|
68
|
+
std: 0.15
|
|
69
|
+
min: 0.1
|
|
70
|
+
max: 0.9
|
|
71
|
+
tariff:
|
|
72
|
+
unit: EUR/kWh
|
|
73
|
+
flat_tariff: 0.30
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Other settings use their documented defaults. For the complete template and
|
|
77
|
+
all parameters, see the [configuration reference](https://pages.persee.minesparis.psl.eu/planeterr/mobev/configuration.html).
|
|
78
|
+
|
|
79
|
+
### Trip files
|
|
80
|
+
|
|
81
|
+
Pass a directory containing `weekday_trips.gpkg` and `weekend_trips.gpkg`.
|
|
82
|
+
Each GeoPackage needs a declared CRS, line geometry, and the fields
|
|
83
|
+
`person_id`, `trip_index`, `preceding_activity_index`,
|
|
84
|
+
`following_activity_index`, `departure_time`, `arrival_time`,
|
|
85
|
+
`preceding_purpose`, `following_purpose`, `is_first`, `is_last`, and `mode`.
|
|
86
|
+
Times are seconds since source-day midnight; only trimmed, case-insensitive
|
|
87
|
+
`car` rows are retained. See the [trip input schema](https://pages.persee.minesparis.psl.eu/planeterr/mobev/inputs.html#trip-inputs).
|
|
88
|
+
|
|
89
|
+
### Tariff files (optional)
|
|
90
|
+
|
|
91
|
+
Configure one or more CSV files under `tariff.files`. Each file has a zero-based
|
|
92
|
+
contiguous integer positional index and exactly one numeric `price` or
|
|
93
|
+
`price_eur_kwh` column in EUR/kWh. Without tariff files, MobEV uses the
|
|
94
|
+
configured flat tariff. Relative paths resolve from the configuration file.
|
|
95
|
+
See [tariff inputs](https://pages.persee.minesparis.psl.eu/planeterr/mobev/inputs.html#tariff-inputs).
|
|
96
|
+
|
|
97
|
+
### Weather file (optional)
|
|
98
|
+
|
|
99
|
+
For `battery.consumption_mode: temperature`, pass a separate CSV or Parquet
|
|
100
|
+
file containing `datetime` and numeric `air_temperature` values in °C.
|
|
101
|
+
Timestamps are normalized to UTC, and every hour in the simulation horizon
|
|
102
|
+
needs coverage. See [weather inputs](https://pages.persee.minesparis.psl.eu/planeterr/mobev/inputs.html#weather-inputs)
|
|
103
|
+
and [battery consumption](https://pages.persee.minesparis.psl.eu/planeterr/mobev/battery-consumption.html).
|
|
104
|
+
|
|
105
|
+
Pass the trip directory, YAML configuration, and weather file separately. The
|
|
106
|
+
[input guide](https://pages.persee.minesparis.psl.eu/planeterr/mobev/inputs.html)
|
|
107
|
+
describes field requirements, validation, and supported behavior.
|
|
108
|
+
|
|
109
|
+
## Run from Python
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from mobev import SimulationPipeline
|
|
113
|
+
|
|
114
|
+
pipeline = SimulationPipeline.from_yaml(
|
|
115
|
+
config_path="config/config.yaml",
|
|
116
|
+
trip_source_dir="data/input/trips/TRIP_FOLDER",
|
|
117
|
+
)
|
|
118
|
+
result = pipeline.run()
|
|
119
|
+
|
|
120
|
+
# Detailed timestep-level charging demand
|
|
121
|
+
print(result.charging_simulation.charging_profiles_df.head())
|
|
122
|
+
|
|
123
|
+
# Combined demand profile (aggregation is separate from run())
|
|
124
|
+
total = pipeline.aggregate(by="total")
|
|
125
|
+
print(total.aggregated_profiles_df.head())
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The default `battery.consumption_mode` is `none`; `season` applies configured
|
|
129
|
+
seasonal factors. For temperature-based consumption, set the mode to
|
|
130
|
+
`temperature` and pass weather separately:
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
pipeline = SimulationPipeline.from_yaml(
|
|
134
|
+
config_path="config/config.yaml",
|
|
135
|
+
trip_source_dir="data/input/trips/TRIP_FOLDER",
|
|
136
|
+
weather_file="data/input/weather.csv",
|
|
137
|
+
)
|
|
138
|
+
result = pipeline.run()
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Run from the command line
|
|
142
|
+
|
|
143
|
+
The installed `mobev` command writes stage tables as Parquet, indicator tables
|
|
144
|
+
as CSV, a log file, and (by default) metadata and analysis plots.
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
mobev \
|
|
148
|
+
--trips-dir data/input/trips/TRIP_FOLDER \
|
|
149
|
+
--output-dir output \
|
|
150
|
+
--config config/config.yaml
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
For temperature-based consumption, also pass the separate weather file:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
mobev \
|
|
157
|
+
--trips-dir data/input/trips/TRIP_FOLDER \
|
|
158
|
+
--output-dir output \
|
|
159
|
+
--config config/config.yaml \
|
|
160
|
+
--weather data/input/weather.csv
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`--trips-dir` and `--output-dir` are required. `--config` defaults to
|
|
164
|
+
`config/config.yaml`; `--save-metadata` and `--analyze-results` default to
|
|
165
|
+
`true`. Use `--max-profiles` to limit plotted vehicle and location groups and
|
|
166
|
+
`--weekday` to add plots for a chosen weekday. See all [CLI options and output
|
|
167
|
+
details](https://pages.persee.minesparis.psl.eu/planeterr/mobev/workflow.html#command-line-runner).
|
|
168
|
+
|
|
169
|
+
## Aggregate and plot results
|
|
170
|
+
|
|
171
|
+
Aggregation operates on a completed run and returns a separate result. For
|
|
172
|
+
example, aggregate charging by location type or by nominal charger power:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
by_location_type = pipeline.aggregate(by="location_type")
|
|
176
|
+
by_charging_power = pipeline.aggregate(
|
|
177
|
+
by="charging_power", charging_powers=[7.4]
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
by_location_type.plot(category="location_type", save_path="by_type.png")
|
|
181
|
+
by_charging_power.plot(category="charging_power_kw", save_path="by_power.png")
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
These category plots show how the load profile is distributed across location
|
|
185
|
+
types and charger power levels:
|
|
186
|
+
|
|
187
|
+

|
|
188
|
+
|
|
189
|
+

|
|
190
|
+
|
|
191
|
+
See the [visualization guide](https://pages.persee.minesparis.psl.eu/planeterr/mobev/visualization.html)
|
|
192
|
+
for aggregation modes, filters, sampling, indicators, and plotting options.
|
|
193
|
+
|
|
194
|
+
## Documentation and project links
|
|
195
|
+
|
|
196
|
+
- [Full documentation](https://pages.persee.minesparis.psl.eu/planeterr/mobev/)
|
|
197
|
+
- [Input formats](https://pages.persee.minesparis.psl.eu/planeterr/mobev/inputs.html)
|
|
198
|
+
- [Configuration reference](https://pages.persee.minesparis.psl.eu/planeterr/mobev/configuration.html)
|
|
199
|
+
- [Charging decision algorithm](https://pages.persee.minesparis.psl.eu/planeterr/mobev/charging-algorithm.html)
|
|
200
|
+
- [Results reference](https://pages.persee.minesparis.psl.eu/planeterr/mobev/results.html)
|
|
201
|
+
- [Changelog](https://pages.persee.minesparis.psl.eu/planeterr/mobev/changelog.html)
|
|
202
|
+
- [Contributing](https://pages.persee.minesparis.psl.eu/planeterr/mobev/contribute.html)
|
|
203
|
+
- [API reference](https://pages.persee.minesparis.psl.eu/planeterr/mobev/api/)
|
|
204
|
+
|
|
205
|
+
Build the docs from a checkout with `uv sync --group docs` followed by
|
|
206
|
+
`make -C docs html`.
|
|
@@ -1,51 +1,63 @@
|
|
|
1
|
-
"""MobEV public API."""
|
|
2
|
-
|
|
3
1
|
from mobev._version import __version__
|
|
4
|
-
from mobev.charging import ChargingSimulator
|
|
5
|
-
from mobev.
|
|
2
|
+
from mobev.charging import ChargingDecisionEngine, ChargingSimulator
|
|
3
|
+
from mobev.config import (
|
|
6
4
|
BatteryConfig,
|
|
7
5
|
ChargingConfig,
|
|
8
6
|
Config,
|
|
7
|
+
EVSegmentConfig,
|
|
9
8
|
FixedVehicleConfig,
|
|
10
9
|
FleetConfig,
|
|
10
|
+
FlexibilityConfig,
|
|
11
11
|
InitialSocConfig,
|
|
12
|
+
LocationChargingConfig,
|
|
13
|
+
PowerDistributionConfig,
|
|
14
|
+
RangeAnxietyConfig,
|
|
12
15
|
SimulationConfig,
|
|
13
|
-
|
|
16
|
+
SocDistributionConfig,
|
|
14
17
|
TariffConfig,
|
|
18
|
+
TariffFileConfig,
|
|
15
19
|
)
|
|
16
|
-
from mobev.
|
|
17
|
-
from mobev.
|
|
20
|
+
from mobev.pipeline import SimulationPipeline
|
|
21
|
+
from mobev.aggregation import ResultsAggregator
|
|
18
22
|
from mobev.results import (
|
|
19
|
-
|
|
23
|
+
AggregatedResults,
|
|
20
24
|
ChargingSimulation,
|
|
21
25
|
Metadata,
|
|
22
26
|
PreparedTrips,
|
|
23
27
|
ScenarioInputs,
|
|
24
28
|
SimulationResults,
|
|
25
29
|
)
|
|
26
|
-
from mobev.scenario import ScenarioBuilder
|
|
30
|
+
from mobev.scenario import ScenarioBuilder, TariffBuilder
|
|
27
31
|
from mobev.trips import TripPreparer
|
|
28
32
|
|
|
29
33
|
__all__ = [
|
|
30
|
-
"
|
|
34
|
+
"AggregatedResults",
|
|
31
35
|
"BatteryConfig",
|
|
32
36
|
"ChargingConfig",
|
|
37
|
+
"ChargingDecisionEngine",
|
|
33
38
|
"ChargingSimulation",
|
|
34
39
|
"ChargingSimulator",
|
|
35
40
|
"Config",
|
|
41
|
+
"EVSegmentConfig",
|
|
36
42
|
"FixedVehicleConfig",
|
|
37
43
|
"FleetConfig",
|
|
44
|
+
"FlexibilityConfig",
|
|
38
45
|
"InitialSocConfig",
|
|
46
|
+
"LocationChargingConfig",
|
|
39
47
|
"Metadata",
|
|
48
|
+
"PowerDistributionConfig",
|
|
40
49
|
"PreparedTrips",
|
|
41
|
-
"
|
|
50
|
+
"ResultsAggregator",
|
|
51
|
+
"RangeAnxietyConfig",
|
|
42
52
|
"ScenarioBuilder",
|
|
43
53
|
"ScenarioInputs",
|
|
44
54
|
"SimulationConfig",
|
|
45
55
|
"SimulationPipeline",
|
|
46
56
|
"SimulationResults",
|
|
47
|
-
"
|
|
57
|
+
"SocDistributionConfig",
|
|
58
|
+
"TariffBuilder",
|
|
48
59
|
"TariffConfig",
|
|
60
|
+
"TariffFileConfig",
|
|
49
61
|
"TripPreparer",
|
|
50
62
|
"__version__",
|
|
51
63
|
]
|