ChaProEV 1.3.4__tar.gz → 2.0.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.
Files changed (175) hide show
  1. {chaproev-1.3.4/src/ChaProEV.egg-info → chaproev-2.0.0}/PKG-INFO +9 -3
  2. {chaproev-1.3.4 → chaproev-2.0.0}/README.md +5 -2
  3. {chaproev-1.3.4 → chaproev-2.0.0}/cha.csv +1 -1
  4. chaproev-2.0.0/moot.png +0 -0
  5. {chaproev-1.3.4 → chaproev-2.0.0}/pyproject.toml +10 -1
  6. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/ChaProEV_run.py +6 -1
  7. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/charging.py +1 -1
  8. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/consumption.py +1 -1
  9. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/define.py +15 -8
  10. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/mobility.py +4 -4
  11. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/profiles.py +37 -36
  12. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/scenarios_module.py +8 -7
  13. chaproev-1.3.4/src/ChaProEV/ChaProEV_plus.py → chaproev-2.0.0/src/ChaProEV/stochastic/ChaProEV_run.py +33 -10
  14. chaproev-2.0.0/src/ChaProEV/stochastic/auxiliary.py +31 -0
  15. chaproev-1.3.4/src/ChaProEV/charging_plus.py → chaproev-2.0.0/src/ChaProEV/stochastic/charging.py +7 -8
  16. chaproev-1.3.4/src/ChaProEV/ChaProEV_dashboard.py → chaproev-2.0.0/src/ChaProEV/stochastic/dashboard.py +12 -3
  17. chaproev-1.3.4/src/ChaProEV/define_plus.py → chaproev-2.0.0/src/ChaProEV/stochastic/define.py +1 -1
  18. chaproev-1.3.4/src/ChaProEV/mobility_plus.py → chaproev-2.0.0/src/ChaProEV/stochastic/mobility.py +7 -7
  19. chaproev-2.0.0/src/ChaProEV/stochastic/scenarios_module.py +25 -0
  20. {chaproev-1.3.4 → chaproev-2.0.0/src/ChaProEV.egg-info}/PKG-INFO +9 -3
  21. {chaproev-1.3.4 → chaproev-2.0.0}/src/ChaProEV.egg-info/SOURCES.txt +21 -18
  22. chaproev-2.0.0/src/ChaProEV.egg-info/entry_points.txt +4 -0
  23. {chaproev-1.3.4 → chaproev-2.0.0}/src/ChaProEV.egg-info/requires.txt +3 -0
  24. {chaproev-1.3.4 → chaproev-2.0.0}/uv.lock +351 -1
  25. chaproev-1.3.4/moot.png +0 -0
  26. {chaproev-1.3.4 → chaproev-2.0.0}/.flake8 +0 -0
  27. {chaproev-1.3.4 → chaproev-2.0.0}/.github/workflows/black-format.yml +0 -0
  28. {chaproev-1.3.4 → chaproev-2.0.0}/.github/workflows/deploy-docs.yml +0 -0
  29. {chaproev-1.3.4 → chaproev-2.0.0}/.github/workflows/draft-pdf.yml +0 -0
  30. {chaproev-1.3.4 → chaproev-2.0.0}/.gitignore +0 -0
  31. {chaproev-1.3.4 → chaproev-2.0.0}/.vscode/ltex.dictionary.en-US.txt +0 -0
  32. {chaproev-1.3.4 → chaproev-2.0.0}/.vscode/settings.json +0 -0
  33. {chaproev-1.3.4 → chaproev-2.0.0}/ChaProEV.pptx +0 -0
  34. {chaproev-1.3.4 → chaproev-2.0.0}/ChaProEV.toml +0 -0
  35. {chaproev-1.3.4 → chaproev-2.0.0}/ChaProEV_prev.pptx +0 -0
  36. {chaproev-1.3.4 → chaproev-2.0.0}/ChaProEV_test_case_configuration_files.zip +0 -0
  37. {chaproev-1.3.4 → chaproev-2.0.0}/Gemfile +0 -0
  38. {chaproev-1.3.4 → chaproev-2.0.0}/LICENCE +0 -0
  39. {chaproev-1.3.4 → chaproev-2.0.0}/MOPO_logo_chaproev on wht.svg +0 -0
  40. {chaproev-1.3.4 → chaproev-2.0.0}/MOPO_logo_chaproev.png +0 -0
  41. {chaproev-1.3.4 → chaproev-2.0.0}/MOPO_logo_chaproev.svg +0 -0
  42. {chaproev-1.3.4 → chaproev-2.0.0}/MOPO_logo_main.svg +0 -0
  43. {chaproev-1.3.4 → chaproev-2.0.0}/MOPO_logo_main_onwhite.svg +0 -0
  44. {chaproev-1.3.4 → chaproev-2.0.0}/README-PC-28624.md +0 -0
  45. {chaproev-1.3.4 → chaproev-2.0.0}/chaproev-1.3.0/.flake8 +0 -0
  46. {chaproev-1.3.4 → chaproev-2.0.0}/chaproev-1.3.0/.gitignore +0 -0
  47. {chaproev-1.3.4 → chaproev-2.0.0}/comparisons/comparison_template.toml +0 -0
  48. {chaproev-1.3.4 → chaproev-2.0.0}/docs/ChaProEV_workflow.png +0 -0
  49. {chaproev-1.3.4 → chaproev-2.0.0}/docs/Legs.png +0 -0
  50. {chaproev-1.3.4 → chaproev-2.0.0}/docs/Locations.png +0 -0
  51. {chaproev-1.3.4 → chaproev-2.0.0}/docs/Makefile +0 -0
  52. {chaproev-1.3.4 → chaproev-2.0.0}/docs/Trips.png +0 -0
  53. {chaproev-1.3.4 → chaproev-2.0.0}/docs/Vehicle_Temperature_correction_factor.svg +0 -0
  54. {chaproev-1.3.4 → chaproev-2.0.0}/docs/_config.yml +0 -0
  55. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/doctrees/environment.pickle +0 -0
  56. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/doctrees/index.doctree +0 -0
  57. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/.buildinfo +0 -0
  58. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_sources/index.rst.txt +0 -0
  59. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_static/alabaster.css +0 -0
  60. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_static/basic.css +0 -0
  61. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_static/custom.css +0 -0
  62. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_static/doctools.js +0 -0
  63. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_static/documentation_options.js +0 -0
  64. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_static/file.png +0 -0
  65. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_static/language_data.js +0 -0
  66. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_static/minus.png +0 -0
  67. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_static/plus.png +0 -0
  68. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_static/pygments.css +0 -0
  69. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_static/searchtools.js +0 -0
  70. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/_static/sphinx_highlight.js +0 -0
  71. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/genindex.html +0 -0
  72. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/index.html +0 -0
  73. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/objects.inv +0 -0
  74. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/search.html +0 -0
  75. {chaproev-1.3.4 → chaproev-2.0.0}/docs/build/html/searchindex.js +0 -0
  76. {chaproev-1.3.4 → chaproev-2.0.0}/docs/charging.md +0 -0
  77. {chaproev-1.3.4 → chaproev-2.0.0}/docs/consumption-PC-28624.md +0 -0
  78. {chaproev-1.3.4 → chaproev-2.0.0}/docs/consumption.md +0 -0
  79. {chaproev-1.3.4 → chaproev-2.0.0}/docs/define-PC-28624.md +0 -0
  80. {chaproev-1.3.4 → chaproev-2.0.0}/docs/define.md +0 -0
  81. {chaproev-1.3.4 → chaproev-2.0.0}/docs/general_parameters-PC-28624.md +0 -0
  82. {chaproev-1.3.4 → chaproev-2.0.0}/docs/general_parameters.md +0 -0
  83. {chaproev-1.3.4 → chaproev-2.0.0}/docs/index-PC-28624.md +0 -0
  84. {chaproev-1.3.4 → chaproev-2.0.0}/docs/index.md +0 -0
  85. {chaproev-1.3.4 → chaproev-2.0.0}/docs/input.md +0 -0
  86. {chaproev-1.3.4 → chaproev-2.0.0}/docs/make.bat +0 -0
  87. {chaproev-1.3.4 → chaproev-2.0.0}/docs/make_variants.md +0 -0
  88. {chaproev-1.3.4 → chaproev-2.0.0}/docs/mobility-PC-28624.md +0 -0
  89. {chaproev-1.3.4 → chaproev-2.0.0}/docs/mobility.md +0 -0
  90. {chaproev-1.3.4 → chaproev-2.0.0}/docs/multiprocessing.md +0 -0
  91. {chaproev-1.3.4 → chaproev-2.0.0}/docs/non_road.md +0 -0
  92. {chaproev-1.3.4 → chaproev-2.0.0}/docs/outputs.md +0 -0
  93. {chaproev-1.3.4 → chaproev-2.0.0}/docs/parallel_processing.md +0 -0
  94. {chaproev-1.3.4 → chaproev-2.0.0}/docs/profiles.md +0 -0
  95. {chaproev-1.3.4 → chaproev-2.0.0}/docs/run_time.md +0 -0
  96. {chaproev-1.3.4 → chaproev-2.0.0}/docs/running_model.md +0 -0
  97. {chaproev-1.3.4 → chaproev-2.0.0}/docs/scenario-PC-28624.md +0 -0
  98. {chaproev-1.3.4 → chaproev-2.0.0}/docs/scenario.md +0 -0
  99. {chaproev-1.3.4 → chaproev-2.0.0}/docs/scenarios_module.md +0 -0
  100. {chaproev-1.3.4 → chaproev-2.0.0}/docs/source/index.rst +0 -0
  101. {chaproev-1.3.4 → chaproev-2.0.0}/docs/using-PC-28624.md +0 -0
  102. {chaproev-1.3.4 → chaproev-2.0.0}/docs/using.md +0 -0
  103. {chaproev-1.3.4 → chaproev-2.0.0}/docs/variants-PC-28624.md +0 -0
  104. {chaproev-1.3.4 → chaproev-2.0.0}/docs/variants.md +0 -0
  105. {chaproev-1.3.4 → chaproev-2.0.0}/docs/weather-PC-28624.md +0 -0
  106. {chaproev-1.3.4 → chaproev-2.0.0}/docs/weather.md +0 -0
  107. {chaproev-1.3.4 → chaproev-2.0.0}/docs/writing.md +0 -0
  108. {chaproev-1.3.4 → chaproev-2.0.0}/eu-emblem-low-res.jpg +0 -0
  109. {chaproev-1.3.4 → chaproev-2.0.0}/input/Mopo/car_own_driveway_percentage.csv +0 -0
  110. {chaproev-1.3.4 → chaproev-2.0.0}/input/Mopo/fleets.csv +0 -0
  111. {chaproev-1.3.4 → chaproev-2.0.0}/mkdocs-PC-28624.yml +0 -0
  112. {chaproev-1.3.4 → chaproev-2.0.0}/mkdocs.yml +0 -0
  113. {chaproev-1.3.4 → chaproev-2.0.0}/non-road/Mopo/NL_domestic-aviation_2040_Aviation gasoline.toml +0 -0
  114. {chaproev-1.3.4 → chaproev-2.0.0}/non-road/Mopo/NL_domestic-aviation_2050_Aviation gasoline.toml +0 -0
  115. {chaproev-1.3.4 → chaproev-2.0.0}/non-road/Mopo/growth_factors.csv +0 -0
  116. {chaproev-1.3.4 → chaproev-2.0.0}/non-road/Mopo/scenario_demands.csv +0 -0
  117. {chaproev-1.3.4 → chaproev-2.0.0}/non-road/Mopo/scenarios.toml +0 -0
  118. {chaproev-1.3.4 → chaproev-2.0.0}/non-road.toml +0 -0
  119. {chaproev-1.3.4 → chaproev-2.0.0}/noot.png +0 -0
  120. {chaproev-1.3.4 → chaproev-2.0.0}/paper/ChaProEV_workflow.png +0 -0
  121. {chaproev-1.3.4 → chaproev-2.0.0}/paper/Legs.png +0 -0
  122. {chaproev-1.3.4 → chaproev-2.0.0}/paper/Locations.png +0 -0
  123. {chaproev-1.3.4 → chaproev-2.0.0}/paper/Trips.png +0 -0
  124. {chaproev-1.3.4 → chaproev-2.0.0}/paper/paper.bib +0 -0
  125. {chaproev-1.3.4 → chaproev-2.0.0}/paper/paper.md +0 -0
  126. {chaproev-1.3.4 → chaproev-2.0.0}/paper/paper.pdf +0 -0
  127. {chaproev-1.3.4 → chaproev-2.0.0}/ref_val.csv +0 -0
  128. {chaproev-1.3.4 → chaproev-2.0.0}/requirements.txt +0 -0
  129. {chaproev-1.3.4 → chaproev-2.0.0}/requirements_obsolete.txt +0 -0
  130. {chaproev-1.3.4 → chaproev-2.0.0}/run_to_OPERA.csv +0 -0
  131. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/Mopo/Latvia_car_own_driveway_2050.toml +0 -0
  132. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/Mopo/Netherlands_urban_car_2030.toml +0 -0
  133. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/Mopo/Switzerland_car_own_driveway_2050.toml +0 -0
  134. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/Mopo/XX_bus.toml +0 -0
  135. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/Mopo/XX_car.toml +0 -0
  136. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/Mopo/XX_truck.toml +0 -0
  137. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/Mopo/XX_van.toml +0 -0
  138. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/bus_test/XX_bus.toml +0 -0
  139. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/cumulative_test/Spain_bus_2050.toml +0 -0
  140. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/cumulative_test/Spain_van_2050.toml +0 -0
  141. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/cumulative_test/XX_car.toml +0 -0
  142. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/cumulative_test/XX_truck.toml +0 -0
  143. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/cumulative_test/XX_van.toml +0 -0
  144. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/local_impact_BEVs/baseline.toml +0 -0
  145. {chaproev-1.3.4 → chaproev-2.0.0}/scenarios/plus/test.toml +0 -0
  146. {chaproev-1.3.4 → chaproev-2.0.0}/setup.cfg +0 -0
  147. {chaproev-1.3.4 → chaproev-2.0.0}/siec.csv +0 -0
  148. {chaproev-1.3.4 → chaproev-2.0.0}/src/ChaProEV/__init__.py +0 -0
  149. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/auxiliary.py +0 -0
  150. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/make_variants.py +0 -0
  151. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/non_road.py +0 -0
  152. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/run_time.py +0 -0
  153. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/weather.py +0 -0
  154. {chaproev-1.3.4/src/ChaProEV → chaproev-2.0.0/src/ChaProEV/classic}/writing.py +0 -0
  155. {chaproev-1.3.4 → chaproev-2.0.0}/src/ChaProEV/py.typed +0 -0
  156. {chaproev-1.3.4 → chaproev-2.0.0}/src/ChaProEV.egg-info/PKG-INFO-PC-28624 +0 -0
  157. {chaproev-1.3.4 → chaproev-2.0.0}/src/ChaProEV.egg-info/PKG-INFO-PC-28624-2 +0 -0
  158. {chaproev-1.3.4 → chaproev-2.0.0}/src/ChaProEV.egg-info/SOURCES-PC-28624-2.txt +0 -0
  159. {chaproev-1.3.4 → chaproev-2.0.0}/src/ChaProEV.egg-info/SOURCES-PC-28624.txt +0 -0
  160. {chaproev-1.3.4 → chaproev-2.0.0}/src/ChaProEV.egg-info/dependency_links.txt +0 -0
  161. {chaproev-1.3.4 → chaproev-2.0.0}/src/ChaProEV.egg-info/requires-PC-28624-2.txt +0 -0
  162. {chaproev-1.3.4 → chaproev-2.0.0}/src/ChaProEV.egg-info/requires-PC-28624.txt +0 -0
  163. {chaproev-1.3.4 → chaproev-2.0.0}/src/ChaProEV.egg-info/top_level.txt +0 -0
  164. {chaproev-1.3.4 → chaproev-2.0.0}/test_bus_moility_matrices/bus_weekday_in_holiday_week.csv +0 -0
  165. {chaproev-1.3.4 → chaproev-2.0.0}/test_bus_moility_matrices/bus_weekday_in_workweek.csv +0 -0
  166. {chaproev-1.3.4 → chaproev-2.0.0}/test_bus_moility_matrices/bus_weekend_in_holiday_week.csv +0 -0
  167. {chaproev-1.3.4 → chaproev-2.0.0}/test_bus_moility_matrices/bus_weekend_in_workweek.csv +0 -0
  168. {chaproev-1.3.4 → chaproev-2.0.0}/tests/test_battery_space.py +0 -0
  169. {chaproev-1.3.4 → chaproev-2.0.0}/tests/test_charge_and_consumption.py +0 -0
  170. {chaproev-1.3.4 → chaproev-2.0.0}/tests/test_empty_values.py +0 -0
  171. {chaproev-1.3.4 → chaproev-2.0.0}/tests/test_enough_power_next_leg.py +0 -0
  172. {chaproev-1.3.4 → chaproev-2.0.0}/tests/test_same_output.py +0 -0
  173. {chaproev-1.3.4 → chaproev-2.0.0}/todo.txt +0 -0
  174. {chaproev-1.3.4 → chaproev-2.0.0}/variants/Mopo/XX_car.csv +0 -0
  175. {chaproev-1.3.4 → chaproev-2.0.0}/variants/Mopo.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ChaProEV
3
- Version: 1.3.4
3
+ Version: 2.0.0
4
4
  Summary: ChaProEV: Charging Profiles of Electric Vehicles
5
5
  Author-email: Omar Usmani <Omar.Usmani@TNO.nl>
6
6
  Project-URL: Homepage, https://github.com/TNO/ChaProEV
@@ -12,11 +12,14 @@ Description-Content-Type: text/markdown
12
12
  License-File: LICENCE
13
13
  Requires-Dist: build>=1.6.1
14
14
  Requires-Dist: ets-cookbook>=1.2.8
15
+ Requires-Dist: eurostat>=1.1.1
15
16
  Requires-Dist: polars>=1.43.2
16
17
  Requires-Dist: python-box>=7.4.1
17
18
  Requires-Dist: streamlit>=1.62.0
18
19
  Requires-Dist: tomli-w>=1.2.0
19
20
  Requires-Dist: tqdm>=4.70.0
21
+ Requires-Dist: twine>=7.0.0
22
+ Requires-Dist: typing>=3.10.0.0
20
23
  Dynamic: license-file
21
24
 
22
25
  # **ChaProEV**
@@ -69,12 +72,14 @@ In that case, the only piece of code you need is as follows (you just need
69
72
  to put the name of the folder where you put your case scenarios instead of the
70
73
  'Mopo' example).
71
74
  ```python
72
- from ChaProEV import ChaProEV_run
75
+ from ChaProEV.classic import ChaProEV_run
73
76
 
74
77
  if __name__ == '__main__':
75
78
  case_name: str = 'Mopo'
76
79
  ChaProEV_run.run_ChaProEV(case_name)
77
80
  ```
81
+
82
+ (In general, replace classic by the mode you want to use)
78
83
  If you installed ChaProEV with pip, then the requirements
79
84
  should be installed as well (see requirements.txt file if you have issues
80
85
  or use the contact below).
@@ -86,13 +91,14 @@ You can use the examples provided in this repository. You can also
86
91
  unzip [this file](https://github.com/TNO/ChaProEV/blob/main/ChaProEV_test_case_configuration_files.zip)
87
92
  into your working folder and use 'test_case' as your case name:
88
93
  ```python
89
- from ChaProEV import ChaProEV_run
94
+ from ChaProEV.classic import ChaProEV_run
90
95
 
91
96
  if __name__ == '__main__':
92
97
  case_name: str = 'test_case'
93
98
  ChaProEV_run.run_ChaProEV(case_name)
94
99
  ```
95
100
 
101
+ (In general, replace classic by the mode you want to use)
96
102
 
97
103
 
98
104
  For examples of running ChaProEV and more configuration files,
@@ -48,12 +48,14 @@ In that case, the only piece of code you need is as follows (you just need
48
48
  to put the name of the folder where you put your case scenarios instead of the
49
49
  'Mopo' example).
50
50
  ```python
51
- from ChaProEV import ChaProEV_run
51
+ from ChaProEV.classic import ChaProEV_run
52
52
 
53
53
  if __name__ == '__main__':
54
54
  case_name: str = 'Mopo'
55
55
  ChaProEV_run.run_ChaProEV(case_name)
56
56
  ```
57
+
58
+ (In general, replace classic by the mode you want to use)
57
59
  If you installed ChaProEV with pip, then the requirements
58
60
  should be installed as well (see requirements.txt file if you have issues
59
61
  or use the contact below).
@@ -65,13 +67,14 @@ You can use the examples provided in this repository. You can also
65
67
  unzip [this file](https://github.com/TNO/ChaProEV/blob/main/ChaProEV_test_case_configuration_files.zip)
66
68
  into your working folder and use 'test_case' as your case name:
67
69
  ```python
68
- from ChaProEV import ChaProEV_run
70
+ from ChaProEV.classic import ChaProEV_run
69
71
 
70
72
  if __name__ == '__main__':
71
73
  case_name: str = 'test_case'
72
74
  ChaProEV_run.run_ChaProEV(case_name)
73
75
  ```
74
76
 
77
+ (In general, replace classic by the mode you want to use)
75
78
 
76
79
 
77
80
  For examples of running ChaProEV and more configuration files,
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
- name: chaproev-1.3.4/cha.csv
2
+ name: chaproev-2.0.0/cha.csv
3
3
  size: 35085865 bytes
4
4
  sha256: c023f8cf501f624ab453eb91bf23c5b735b0be2faa0c5352317fafde5feeec5e
Binary file
@@ -4,7 +4,7 @@ build-backend = 'setuptools.build_meta'
4
4
 
5
5
  [project]
6
6
  name = 'ChaProEV'
7
- version = '1.3.4'
7
+ version = '2.0.0'
8
8
  authors = [
9
9
  { name='Omar Usmani', email='Omar.Usmani@TNO.nl' },
10
10
  ]
@@ -19,11 +19,14 @@ classifiers = [
19
19
  dependencies = [
20
20
  "build>=1.6.1",
21
21
  "ets-cookbook>=1.2.8",
22
+ "eurostat>=1.1.1",
22
23
  "polars>=1.43.2",
23
24
  "python-box>=7.4.1",
24
25
  "streamlit>=1.62.0",
25
26
  "tomli-w>=1.2.0",
26
27
  "tqdm>=4.70.0",
28
+ "twine>=7.0.0",
29
+ "typing>=3.10.0.0",
27
30
  ]
28
31
  # dynamic = ['dependencies']
29
32
  # [tool.setuptools.dynamic]
@@ -38,6 +41,12 @@ where = ['src']
38
41
  [tool.pytest.ini_options]
39
42
  pythonpath = ['src/ChaProEV']
40
43
 
44
+
45
+ [project.scripts]
46
+ classic = 'ChaProEV.classic.ChaProEV_run:test_run'
47
+ stochastic = 'ChaProEV.stochastic.ChaProEV_run:test_run'
48
+ dashboard = 'ChaProEV.stochastic.dashboard:run_dashboard'
49
+
41
50
  [project.urls]
42
51
  'Homepage' = 'https://github.com/TNO/ChaProEV'
43
52
 
@@ -11,7 +11,7 @@ from box import Box
11
11
  from ETS_CookBook import ETS_CookBook as cook
12
12
  from tqdm.rich import tqdm
13
13
 
14
- from ChaProEV import make_variants, profiles, scenarios_module, writing
14
+ from ChaProEV.classic import make_variants, profiles, scenarios_module, writing
15
15
 
16
16
 
17
17
  @cook.function_timer
@@ -69,6 +69,11 @@ def run_ChaProEV(case_name: str) -> None:
69
69
  writing.extra_end_outputs(case_name, general_parameters)
70
70
 
71
71
 
72
+ def test_run() -> None:
73
+ case_name: str = 'Mopo'
74
+ run_ChaProEV(case_name)
75
+
76
+
72
77
  if __name__ == '__main__':
73
78
  # This is a case name, which is the grouping of all your scenarios.
74
79
  # This is principally used to label your output files.
@@ -7,7 +7,7 @@ from box import Box
7
7
  from ETS_CookBook import ETS_CookBook as cook
8
8
  from rich import print
9
9
 
10
- from ChaProEV import mobility, run_time
10
+ from ChaProEV.classic import mobility, run_time
11
11
 
12
12
 
13
13
  def get_time_modulation(
@@ -7,7 +7,7 @@ import pandas as pd
7
7
  from box import Box
8
8
  from ETS_CookBook import ETS_CookBook as cook
9
9
 
10
- from ChaProEV import run_time
10
+ from ChaProEV.classic import run_time
11
11
 
12
12
 
13
13
  def create_consumption_tables(
@@ -19,6 +19,7 @@ to run that function for all class types.
19
19
 
20
20
  import datetime
21
21
  import math
22
+ from typing import TypeVar
22
23
 
23
24
  import numpy as np
24
25
  import pandas as pd
@@ -26,7 +27,7 @@ from box import Box
26
27
  from ETS_CookBook import ETS_CookBook as cook
27
28
  from rich import print
28
29
 
29
- from ChaProEV import run_time
30
+ from ChaProEV.classic import run_time
30
31
 
31
32
 
32
33
  def get_trip_charging_sessions(
@@ -1578,9 +1579,15 @@ class TripChargingSession:
1578
1579
  )
1579
1580
 
1580
1581
 
1582
+ ScenarioObject = TypeVar(
1583
+ 'ScenarioObject',
1584
+ bound=Leg | Location | Trip,
1585
+ )
1586
+
1587
+
1581
1588
  def declare_class_instances(
1582
- ChosenClass: type, scenario: Box, general_parameters: Box
1583
- ) -> list[type]:
1589
+ ChosenClass: type[ScenarioObject], scenario: Box, general_parameters: Box
1590
+ ) -> list[ScenarioObject]:
1584
1591
  '''
1585
1592
  This function creates the instances of a class (ChosenClass),
1586
1593
  based on a scenario file name where the instances and their properties
@@ -1591,7 +1598,7 @@ def declare_class_instances(
1591
1598
 
1592
1599
  class_instances: list[str] = scenario[class_name]
1593
1600
 
1594
- instances: list[type] = []
1601
+ instances: list[ScenarioObject] = []
1595
1602
 
1596
1603
  for class_instance in class_instances:
1597
1604
  append_instance: bool = True
@@ -1619,7 +1626,7 @@ def declare_class_instances(
1619
1626
  # @cook.function_timer
1620
1627
  def declare_all_instances(
1621
1628
  scenario: Box, case_name: str, general_parameters: Box
1622
- ) -> tuple[pd.DataFrame, list[type], list[type], list[type]]:
1629
+ ) -> tuple[pd.DataFrame, list[Leg], list[Location], list[Trip]]:
1623
1630
  '''
1624
1631
  This declares all instances of the various objects
1625
1632
  (legs, locations, trips).
@@ -1627,11 +1634,11 @@ def declare_all_instances(
1627
1634
  scenario_name: str = scenario.name
1628
1635
  file_parameters: Box = general_parameters.files
1629
1636
  output_folder: str = f'{file_parameters.output_root}/{case_name}'
1630
- locations: list[type] = declare_class_instances(
1637
+ locations: list[Location] = declare_class_instances(
1631
1638
  Location, scenario, general_parameters
1632
1639
  )
1633
1640
 
1634
- legs: list[type] = declare_class_instances(
1641
+ legs: list[Leg] = declare_class_instances(
1635
1642
  Leg, scenario, general_parameters
1636
1643
  )
1637
1644
 
@@ -1673,7 +1680,7 @@ def declare_all_instances(
1673
1680
  f'{output_folder}/{scenario_name}_location_connections.pkl'
1674
1681
  )
1675
1682
 
1676
- trips: list[type] = declare_class_instances(
1683
+ trips: list[Trip] = declare_class_instances(
1677
1684
  Trip, scenario, general_parameters
1678
1685
  )
1679
1686
 
@@ -22,7 +22,7 @@ from box import Box
22
22
  from ETS_CookBook import ETS_CookBook as cook
23
23
  from rich import print
24
24
 
25
- from ChaProEV import define, run_time
25
+ from ChaProEV.classic import run_time, define
26
26
 
27
27
 
28
28
  class ChargingSession:
@@ -1950,9 +1950,9 @@ def get_kilometers_for_next_leg(
1950
1950
  # @cook.function_timer
1951
1951
  def make_mobility_data(
1952
1952
  location_connections: pd.DataFrame,
1953
- legs: define.Leg,
1954
- locations: define.Location,
1955
- trips: define.Trip,
1953
+ legs: list[define.Leg],
1954
+ locations: list[define.Location],
1955
+ trips: list[define.Trip],
1956
1956
  scenario: Box,
1957
1957
  case_name: str,
1958
1958
  general_parameters: Box,
@@ -7,7 +7,8 @@ import numpy as np
7
7
  import pandas as pd
8
8
  from box import Box
9
9
 
10
- from ChaProEV import run_time
10
+ from ChaProEV.classic import run_time
11
+
11
12
 
12
13
  # @cook.function_timer
13
14
  def car_home_parking(case_name: str, general_parameters: Box) -> None:
@@ -160,9 +161,9 @@ def car_home_parking(case_name: str, general_parameters: Box) -> None:
160
161
  + (1 - own_driveway_percentage)
161
162
  * on_street_values_from_network_from_sessions[quantity]
162
163
  )
163
- sessions_values_columns: list[
164
- str
165
- ] = home_type_parameters.sessions_values_columns
164
+ sessions_values_columns: list[str] = (
165
+ home_type_parameters.sessions_values_columns
166
+ )
166
167
  for quantity in sessions_values_columns:
167
168
  charging_sessions_own_driveway_values[
168
169
  quantity
@@ -224,13 +225,13 @@ def fleet_profiles(
224
225
  distance_header: str = consumption_parameters.distance_header
225
226
  fleet_distance_header: str = consumption_parameters.fleet_distance_header
226
227
 
227
- energy_carriers_consumption_names: list[
228
- str
229
- ] = consumption_parameters.energy_carriers_consumption_names
228
+ energy_carriers_consumption_names: list[str] = (
229
+ consumption_parameters.energy_carriers_consumption_names
230
+ )
230
231
 
231
- fleet_energy_carriers_consumption_names: list[
232
- str
233
- ] = consumption_parameters.fleet_energy_carriers_consumption_names
232
+ fleet_energy_carriers_consumption_names: list[str] = (
233
+ consumption_parameters.fleet_energy_carriers_consumption_names
234
+ )
234
235
  energy_carriers: list[str] = consumption_parameters.energy_carriers
235
236
  output_root: str = general_parameters.files.output_root
236
237
  output_folder: str = f'{output_root}/{case_name}'
@@ -330,9 +331,9 @@ def fleet_profiles(
330
331
  sessions_dataframe_params: Box = (
331
332
  general_parameters.sessions_dataframe
332
333
  )
333
- fleet_display_dataframe_headers: list[
334
- str
335
- ] = sessions_dataframe_params.fleet_display_dataframe_headers
334
+ fleet_display_dataframe_headers: list[str] = (
335
+ sessions_dataframe_params.fleet_display_dataframe_headers
336
+ )
336
337
  fleet_sessions: pd.DataFrame = pd.DataFrame(
337
338
  columns=fleet_display_dataframe_headers,
338
339
  index=reference_sessions.index,
@@ -432,9 +433,9 @@ def make_profile_display_dataframe(
432
433
  output_root: str = general_parameters.files.output_root
433
434
  output_folder: str = f'{output_root}/{case_name}'
434
435
 
435
- profile_dataframe_headers: list[
436
- str
437
- ] = general_parameters.profile_dataframe.headers
436
+ profile_dataframe_headers: list[str] = (
437
+ general_parameters.profile_dataframe.headers
438
+ )
438
439
  profile_dataframe: pd.DataFrame = run_time.get_time_stamped_dataframe(
439
440
  scenario, general_parameters, locations_as_columns=False
440
441
  )
@@ -481,12 +482,12 @@ def make_sessions_display_dataframes(
481
482
  .between(display_range[0], display_range[-1])
482
483
  ]
483
484
  )
484
- display_session_headers: list[
485
- str
486
- ] = general_parameters.sessions_dataframe.display_dataframe_headers
487
- display_session_index: list[
488
- str
489
- ] = general_parameters.sessions_dataframe.display_dataframe_index
485
+ display_session_headers: list[str] = (
486
+ general_parameters.sessions_dataframe.display_dataframe_headers
487
+ )
488
+ display_session_index: list[str] = (
489
+ general_parameters.sessions_dataframe.display_dataframe_index
490
+ )
490
491
 
491
492
  display_charging_sessions: pd.DataFrame = (
492
493
  charging_sessions_with_charged_amounts[
@@ -502,15 +503,15 @@ def make_sessions_display_dataframes(
502
503
  / display_charging_sessions['Vehicle Discharge Power (kW)']
503
504
  )
504
505
 
505
- display_charging_sessions[
506
- 'Effective discharge efficiency'
507
- ] = display_charging_sessions['Effective discharge efficiency'].fillna(
508
- general_parameters.discharge.no_discharge_efficiency_output
506
+ display_charging_sessions['Effective discharge efficiency'] = (
507
+ display_charging_sessions['Effective discharge efficiency'].fillna(
508
+ general_parameters.discharge.no_discharge_efficiency_output
509
+ )
509
510
  )
510
- display_charging_sessions[
511
- 'Effective charging efficiency'
512
- ] = display_charging_sessions['Effective charging efficiency'].fillna(
513
- general_parameters.discharge.no_charge_efficiency_output
511
+ display_charging_sessions['Effective charging efficiency'] = (
512
+ display_charging_sessions['Effective charging efficiency'].fillna(
513
+ general_parameters.discharge.no_charge_efficiency_output
514
+ )
514
515
  )
515
516
 
516
517
  display_charging_sessions.to_pickle(
@@ -544,12 +545,12 @@ def make_display_totals(
544
545
  ].sum()
545
546
  display_run_totals: pd.Series = pd.Series()
546
547
  display_run_totals['Kilometers'] = display_run_kilometrage
547
- display_run_totals[
548
- 'Charge drawn by vehicles (kWh)'
549
- ] = display_run_charge_drwan_by_vehicles
550
- display_run_totals[
551
- 'Charge drawn from network (kWh)'
552
- ] = display_run_charge_from_network
548
+ display_run_totals['Charge drawn by vehicles (kWh)'] = (
549
+ display_run_charge_drwan_by_vehicles
550
+ )
551
+ display_run_totals['Charge drawn from network (kWh)'] = (
552
+ display_run_charge_from_network
553
+ )
553
554
  display_run_totals['Charging costs (€)'] = display_run_charging_costs
554
555
  input_root: str = general_parameters.files.input_root
555
556
  input_folder: str = f'{input_root}/{case_name}'
@@ -4,13 +4,14 @@ This is where you run the model
4
4
  '''
5
5
 
6
6
  import os
7
+ from pathlib import Path
7
8
 
8
9
  import pandas as pd
9
10
  from box import Box
10
11
  from ETS_CookBook import ETS_CookBook as cook
11
12
  from rich import print
12
13
 
13
- from ChaProEV import charging, consumption, define, mobility, profiles
14
+ from ChaProEV.classic import charging, consumption, define, mobility, profiles
14
15
 
15
16
 
16
17
  @cook.function_timer
@@ -155,21 +156,21 @@ def run_scenario(
155
156
  # @cook.function_timer
156
157
  def load_scenarios(case_name: str) -> list[Box]:
157
158
  scenario_folder_files: list[str] = os.listdir(f'scenarios/{case_name}')
158
- scenario_files: list[str] = [
159
+ scenario_file_names: list[str] = [
159
160
  scenario_folder_file
160
161
  for scenario_folder_file in scenario_folder_files
161
162
  if scenario_folder_file.split('.')[1] == 'toml'
162
163
  ]
163
- scenario_file_paths: list[str] = [
164
- f'scenarios/{case_name}/{scenario_file}'
165
- for scenario_file in scenario_files
164
+ scenario_file_paths: list[Path] = [
165
+ Path(f'scenarios/{case_name}/{scenario_file_name}')
166
+ for scenario_file_name in scenario_file_names
166
167
  ]
167
168
  scenarios: list[Box] = [
168
169
  cook.parameters_from_TOML(scenario_file_path)
169
170
  for scenario_file_path in scenario_file_paths
170
171
  ]
171
- for scenario, scenario_file in zip(scenarios, scenario_files):
172
- scenario.name = scenario_file.split('.')[0]
172
+ for scenario, scenario_file_name in zip(scenarios, scenario_file_names):
173
+ scenario.name = scenario_file_name.split('.')[0]
173
174
  return scenarios
174
175
 
175
176
 
@@ -8,7 +8,13 @@ from box import Box
8
8
  from ETS_CookBook import ETS_CookBook as cook
9
9
  from rich import print
10
10
 
11
- from ChaProEV import auxiliary, charging_plus, define_plus, mobility_plus
11
+ from ChaProEV.stochastic import (
12
+ auxiliary,
13
+ charging,
14
+ define,
15
+ mobility,
16
+ scenarios_module,
17
+ )
12
18
 
13
19
 
14
20
  @dataclass
@@ -84,18 +90,18 @@ def get_charging_quantities(
84
90
  run_trips,
85
91
  base_trips,
86
92
  locations,
87
- ) = define_plus.define_user(
93
+ ) = define.define_user(
88
94
  scenario=scenario, random_generator=random_generators.define
89
95
  )
90
96
 
91
- mobility_matrix: pl.DataFrame = mobility_plus.compute_mobility_matrix(
97
+ mobility_matrix: pl.DataFrame = mobility.compute_mobility_matrix(
92
98
  time_ranges=time_ranges,
93
99
  run_trips=run_trips,
94
100
  base_trips=base_trips,
95
101
  scenario=scenario,
96
102
  )
97
103
 
98
- charging_dataframe = charging_plus.compute_charging(
104
+ charging_dataframe = charging.compute_charging(
99
105
  mobility_matrix=mobility_matrix,
100
106
  locations=locations,
101
107
  scenario=scenario,
@@ -145,7 +151,7 @@ def get_iterated_charging_dataframe(
145
151
 
146
152
 
147
153
  @cook.function_timer
148
- def run_ChaProEV(scenario: Box) -> tuple[pl.DataFrame, pl.DataFrame]:
154
+ def run_ChaProEV_scenario(scenario: Box) -> tuple[pl.DataFrame, pl.DataFrame]:
149
155
  random_generators: auxiliary.RandomGenerators = (
150
156
  auxiliary.RandomGenerators.create_generators(scenario=scenario)
151
157
  )
@@ -157,22 +163,30 @@ def run_ChaProEV(scenario: Box) -> tuple[pl.DataFrame, pl.DataFrame]:
157
163
  iterations=iterations,
158
164
  random_generators=random_generators,
159
165
  )
160
- hourly_values: pl.DataFrame = charging_plus.get_hourly_values(
166
+ hourly_values: pl.DataFrame = charging.get_hourly_values(
161
167
  charging_dataframe
162
168
  )
163
169
 
164
170
  return charging_dataframe, hourly_values
165
171
 
166
172
 
167
- if __name__ == '__main__':
173
+ def run_ChaProEV(case_name: str) -> None:
174
+
175
+ scenarios: list[Box] = scenarios_module.load_scenarios(case_name=case_name)
176
+ for scenario in scenarios:
177
+ run_ChaProEV_scenario(scenario=scenario)
178
+
179
+
180
+ def test_run() -> None:
168
181
 
169
182
  scenario_path: Path = Path('scenarios/plus/test.toml')
170
183
  scenario: Box = cook.parameters_from_TOML(scenario_path)
171
-
172
184
  plt.style.use('fivethirtyeight')
173
185
  network_power_figure, network_power_plot = plt.subplots(1, 1)
174
186
 
175
- charging_dataframe, hourly_values = run_ChaProEV(scenario=scenario)
187
+ charging_dataframe, hourly_values = run_ChaProEV_scenario(
188
+ scenario=scenario
189
+ )
176
190
  network_power_plot.bar(
177
191
  x=hourly_values['Hour number'],
178
192
  height=hourly_values['Average power drawn from network (kW)'],
@@ -180,12 +194,21 @@ if __name__ == '__main__':
180
194
  network_power_figure.savefig('noot.png')
181
195
 
182
196
  scenario.charging.adaptive = True
183
- charging_dataframe, hourly_values = run_ChaProEV(scenario=scenario)
197
+ charging_dataframe, hourly_values = run_ChaProEV_scenario(
198
+ scenario=scenario
199
+ )
184
200
  network_power_plot.bar(
185
201
  x=hourly_values['Hour number'],
186
202
  height=hourly_values['Average power drawn from network (kW)'],
187
203
  )
188
204
  network_power_figure.savefig('moot.png')
205
+
206
+
207
+ if __name__ == '__main__':
208
+
209
+ case_name: str = 'plus'
210
+ run_ChaProEV(case_name=case_name)
211
+
189
212
  # plot1, plot2 = st.columns(2)
190
213
  # with plot1:
191
214
  # st.pyplot(network_power_figure)
@@ -0,0 +1,31 @@
1
+ from dataclasses import dataclass
2
+
3
+ import numpy as np
4
+ from box import Box
5
+
6
+
7
+ @dataclass
8
+ class RandomGenerators:
9
+ define: np.random.Generator
10
+ mobility: np.random.Generator
11
+ charging: np.random.Generator
12
+
13
+ @staticmethod
14
+ def create_generators(scenario: Box) -> RandomGenerators:
15
+ run_parameters: Box = scenario.run
16
+ if run_parameters.use_seed:
17
+ run_seed: int | None = run_parameters.seed
18
+ else:
19
+ run_seed = None
20
+
21
+ seed_sequence: np.random.SeedSequence = np.random.SeedSequence(
22
+ run_seed
23
+ )
24
+
25
+ define_seed, mobility_seed, charging_seed = seed_sequence.spawn(3)
26
+
27
+ return RandomGenerators(
28
+ define=np.random.default_rng(seed=define_seed),
29
+ mobility=np.random.default_rng(seed=mobility_seed),
30
+ charging=np.random.default_rng(seed=charging_seed),
31
+ )
@@ -6,14 +6,14 @@ from box import Box
6
6
  from ETS_CookBook import ETS_CookBook as cook
7
7
  from rich import print
8
8
 
9
- from ChaProEV import auxiliary, define_plus, mobility_plus
9
+ from ChaProEV.stochastic import auxiliary, define, mobility
10
10
 
11
11
 
12
12
  @cook.function_timer
13
13
  def compute_charging(
14
14
  *,
15
15
  mobility_matrix: pl.DataFrame,
16
- locations: dict[str, define_plus.Location],
16
+ locations: dict[str, define.Location],
17
17
  scenario: Box,
18
18
  random_generator: np.random.Generator,
19
19
  ) -> pl.DataFrame:
@@ -72,7 +72,7 @@ def compute_charging(
72
72
  previous_location_name = location_name
73
73
 
74
74
  else:
75
- location: define_plus.Location = locations[location_name]
75
+ location: define.Location = locations[location_name]
76
76
  if (previous_location_name == driving_location_name) and (
77
77
  location_name != driving_location_name
78
78
  ):
@@ -84,13 +84,12 @@ def compute_charging(
84
84
  can_charge = (
85
85
  random_generator.random() < location.connectivity
86
86
  )
87
-
88
87
  does_charge = wants_to_charge and can_charge
88
+
89
+ if does_charge:
89
90
  battery_space_at_session_start_kWh: float = (
90
91
  battery_capacity_kWh - current_battery_level_kWh
91
92
  )
92
-
93
- if does_charge:
94
93
  available_power_kW: float = location.charging_power_kW
95
94
  hour_in_day: int = time_stamp.hour
96
95
  modulation_factor: float = (
@@ -218,11 +217,11 @@ if __name__ == '__main__':
218
217
  run_trips,
219
218
  base_trips,
220
219
  locations,
221
- ) = define_plus.define_user(
220
+ ) = define.define_user(
222
221
  scenario=scenario, random_generator=random_generators.define
223
222
  )
224
223
 
225
- mobility_matrix: pl.DataFrame = mobility_plus.compute_mobility_matrix(
224
+ mobility_matrix: pl.DataFrame = mobility.compute_mobility_matrix(
226
225
  time_ranges=time_ranges,
227
226
  run_trips=run_trips,
228
227
  base_trips=base_trips,
@@ -1,3 +1,5 @@
1
+ import subprocess
2
+ import sys
1
3
  from pathlib import Path
2
4
 
3
5
  import matplotlib.pyplot as plt
@@ -6,7 +8,7 @@ import streamlit as st
6
8
  from box import Box
7
9
  from ETS_CookBook import ETS_CookBook as cook
8
10
 
9
- from ChaProEV import ChaProEV_plus
11
+ from ChaProEV.stochastic import ChaProEV_run
10
12
 
11
13
 
12
14
  def make_dashboard() -> None:
@@ -152,10 +154,10 @@ def make_dashboard() -> None:
152
154
  * scenario_A.trips.weekend_trip.start_time_hours_standard_deviation
153
155
  )
154
156
 
155
- charging_dataframe_A, hourly_values_A = ChaProEV_plus.run_ChaProEV(
157
+ charging_dataframe_A, hourly_values_A = ChaProEV_run.run_ChaProEV_scenario(
156
158
  scenario=scenario_A
157
159
  )
158
- charging_dataframe_B, hourly_values_B = ChaProEV_plus.run_ChaProEV(
160
+ charging_dataframe_B, hourly_values_B = ChaProEV_run.run_ChaProEV_scenario(
159
161
  scenario=scenario_B
160
162
  )
161
163
 
@@ -187,6 +189,13 @@ def make_dashboard() -> None:
187
189
  plt.close(network_power_figure)
188
190
 
189
191
 
192
+ def run_dashboard() -> None:
193
+ app_path: Path = Path(__file__).resolve()
194
+ subprocess.run(
195
+ [sys.executable, '-m', 'streamlit', 'run', str(app_path)], check=True
196
+ )
197
+
198
+
190
199
  if __name__ == '__main__':
191
200
 
192
201
  make_dashboard()