From fff7eb68f2135c7853808ae7dcfc8a027f202641 Mon Sep 17 00:00:00 2001 From: adrienmellot Date: Wed, 13 Mar 2024 15:00:15 +0100 Subject: [PATCH 1/3] Implement realistic timeseries for transport demand #271 --- CHANGELOG.md | 2 +- config/default.yaml | 4 +- config/schema.yaml | 6 +- rules/data.smk | 6 +- rules/transport.smk | 34 ++++--- scripts/transport/aggregate_timeseries.py | 18 ++-- scripts/transport/jrc_idees.py | 7 +- .../transport/road_transport_timeseries.py | 89 +++++++++++++------ 8 files changed, 107 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f507f28b..01fdaf38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Added (models) -* **ADD** fully-electrified road transportation (#270). +* **ADD** fully-electrified road transportation (#270), (#271). * **ADD** nuclear power plant technology with capacity limits. Capacity limits can be equal to today or be bound by a minimum and maximum capacity to represent an available range in future. In either case, capacities are allocated at a subnational resolution based on linear scaling from current capacity geolocations, using the JRC power plant database (#78). diff --git a/config/default.yaml b/config/default.yaml index c4001502..12d4add0 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -17,6 +17,7 @@ data-sources: eurostat-energy-balance: https://raw.githubusercontent.com/calliope-project/euro-calliope-datasets/feature-sector-coupling/eurostat/nrg_bal_c.tsv.gz # FIXME do not use cached data swiss-energy-balance: https://www.bfe.admin.ch/bfe/en/home/versorgung/statistik-und-geodaten/energiestatistiken/gesamtenergiestatistik.exturl.html/aHR0cHM6Ly9wdWJkYi5iZmUuYWRtaW4uY2gvZGUvcHVibGljYX/Rpb24vZG93bmxvYWQvNzUxOQ==.html swiss-industry-energy-balance: https://www.bfe.admin.ch/bfe/en/home/versorgung/statistik-und-geodaten/energiestatistiken/teilstatistiken.exturl.html/aHR0cHM6Ly9wdWJkYi5iZmUuYWRtaW4uY2gvZGUvcHVibGljYX/Rpb24vZG93bmxvYWQvODc4OA==.html + ev-data: https://zenodo.org/record/6579421/files/ramp-ev-consumption-profiles.csv.gz?download=1 root-directory: . cluster-sync: url: euler.ethz.ch @@ -134,7 +135,7 @@ parameters: coaches-and-buses: 3248 passenger-cars: 324 motorcycles: 200 # based on passenger car electrical efficiency scaled by relative diesel efficiency - names: + vehicle-type-names: light-duty-vehicles: Light duty vehicles heavy-duty-vehicles: Heavy duty vehicles coaches-and-buses: Motor coaches, buses and trolley buses @@ -144,6 +145,7 @@ parameters: ALB: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] BIH: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] MNE: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] + MKD: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] SRB: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] NOR: ['SWE', 'DNK'] CHE: ['DEU', 'AUT', 'FRA', 'ITA'] diff --git a/config/schema.yaml b/config/schema.yaml index 4d5f52e6..794acfa0 100644 --- a/config/schema.yaml +++ b/config/schema.yaml @@ -95,6 +95,10 @@ properties: type: string pattern: ^(https?|http?):\/\/.+ description: Web address of Swiss industry energy balance data. + ev-data: + type: string + pattern: ^(https?|http?):\/\/.+ + description: Web address of electric vehicle data. root-directory: type: string description: Path to the root directory of euro-calliope containing scripts and template folders. @@ -282,7 +286,7 @@ properties: motorcycles: type: number description: Motorcylces. - names: + vehicle-type-names: type: object description: Names of vehicle types in JRC-IDEES. additionalProperties: false diff --git a/rules/data.smk b/rules/data.smk index 4df5859a..3d85e87a 100644 --- a/rules/data.smk +++ b/rules/data.smk @@ -8,6 +8,7 @@ rule download_ch_energy_balances: params: url = lambda wildcards: config["data-sources"][f"swiss-{wildcards.dataset}"] output: protected("data/automatic/ch-{dataset}.xlsx") + conda: "../envs/shell.yaml" wildcard_constraints: dataset = "((energy-balance)|(industry-energy-balance))" localrule: True @@ -21,6 +22,7 @@ rule download_eurostat_annual_energy_balances: message: "Download Eurostat Annual Energy Balances from euro-calliope datasets" params: url = config["data-sources"]["eurostat-energy-balance"] + conda: "../envs/shell.yaml" output: protected("data/automatic/eurostat-energy-balance.tsv.gz") localrule: True shell: "curl -sLo {output} {params.url}" @@ -81,7 +83,9 @@ rule jrc_idees_transport_processed: country_code=EU28 ) output: "build/data/jrc-idees/transport/processed-{dataset}.csv" + params: + vehicle_type_names = config["parameters"]["transport"]["vehicle-type-names"], wildcard_constraints: - dataset = "((road-energy)|(road-distance)|(road-vehicles))" + dataset = "road-energy|road-distance|road-vehicles" conda: "../envs/default.yaml" script: "../scripts/transport/jrc_idees.py" diff --git a/rules/transport.smk b/rules/transport.smk index 521d1deb..e084bfcb 100644 --- a/rules/transport.smk +++ b/rules/transport.smk @@ -1,5 +1,13 @@ """Rules to process transport sector data.""" +rule download_transport_timeseries: + message: "Get EV data from RAMP" + params: + url = config["data-sources"]["ev-data"] + conda: "../envs/shell.yaml" + output: protected("data/automatic/ramp-ev-consumption-profiles.csv.gz") + localrule: True + shell: "curl -sLo {output} {params.url}" rule annual_transport_demand: message: "Calculate future transport energy demand based on JRC IDEES" @@ -23,35 +31,37 @@ rule annual_transport_demand: rule create_road_transport_timeseries: message: "Create timeseries for road transport demand" input: - data = "build/data/transport/annual-road-transport-distance-demand.csv", + annual_data = "build/data/transport/annual-road-transport-distance-demand.csv", + timeseries = "data/automatic/ramp-ev-consumption-profiles.csv.gz" params: first_year = config["scope"]["temporal"]["first-year"], final_year = config["scope"]["temporal"]["final-year"], power_scaling_factor = config["scaling-factors"]["power"], - conversion_factor = lambda wildcards: config["parameters"]["transport"]["road-transport-conversion-factors"][wildcards.type], - type_name = lambda wildcards: config["parameters"]["transport"]["names"][wildcards.type], - historic = False + conversion_factor = lambda wildcards: config["parameters"]["transport"]["road-transport-conversion-factors"][wildcards.vehicle_type], + historic = False, + countries = config["scope"]["spatial"]["countries"], conda: "../envs/default.yaml" wildcard_constraints: - type = "light-duty-vehicles|heavy-duty-vehicles|coaches-and-buses|passenger-cars|motorcycles" + vehicle_type = "light-duty-vehicles|heavy-duty-vehicles|coaches-and-buses|passenger-cars|motorcycles" output: - main = "build/data/transport/timeseries/timeseries-{type}.csv", + main = "build/data/transport/timeseries/timeseries-{vehicle_type}.csv", script: "../scripts/transport/road_transport_timeseries.py" use rule create_road_transport_timeseries as create_road_transport_timeseries_historic_electrification with: message: "Create timeseries for historic electrified road transport demand" input: - data = "build/data/transport/annual-road-transport-historic-electrification.csv" + annual_data = "build/data/transport/annual-road-transport-historic-electrification.csv", + timeseries = "data/automatic/ramp-ev-consumption-profiles.csv.gz", params: first_year = config["scope"]["temporal"]["first-year"], final_year = config["scope"]["temporal"]["final-year"], power_scaling_factor = config["scaling-factors"]["power"], - conversion_factor = lambda wildcards: config["parameters"]["transport"]["road-transport-conversion-factors"][wildcards.type], - type_name = lambda wildcards: config["parameters"]["transport"]["names"][wildcards.type], - historic = True + conversion_factor = lambda wildcards: config["parameters"]["transport"]["road-transport-conversion-factors"][wildcards.vehicle_type], + historic = True, + countries = config["scope"]["spatial"]["countries"], output: - "build/data/transport/timeseries/timeseries-{type}-historic-electrification.csv" + "build/data/transport/timeseries/timeseries-{vehicle_type}-historic-electrification.csv" rule aggregate_timeseries: # TODO consider merge with other rules, as this is tiny atm @@ -65,8 +75,6 @@ rule aggregate_timeseries: # TODO consider merge with other rules, as this is ti "build/data/transport/timeseries/timeseries-motorcycles.csv"), locations = "build/data/regional/units.csv", populations = "build/data/regional/population.csv" - params: - countries = config["scope"]["spatial"]["countries"] conda: "../envs/default.yaml" output: "build/models/{resolution}/timeseries/demand/electrified-road-transport.csv", diff --git a/scripts/transport/aggregate_timeseries.py b/scripts/transport/aggregate_timeseries.py index 77e01684..c094c873 100644 --- a/scripts/transport/aggregate_timeseries.py +++ b/scripts/transport/aggregate_timeseries.py @@ -2,22 +2,21 @@ import pycountry -def create_continental_timeseries(paths_to_input: list[str], country_codes: list[str]) -> pd.DataFrame: - ts = create_national_timeseries(paths_to_input, country_codes) +def create_continental_timeseries(paths_to_input: list[str]) -> pd.DataFrame: + ts = create_national_timeseries(paths_to_input) return ts.sum(axis=1).rename("EUR") -def create_national_timeseries(paths_to_input: list[str], country_codes: list[str]) -> pd.DataFrame: +def create_national_timeseries(paths_to_input: list[str]) -> pd.DataFrame: all_ts = [ pd.read_csv(path, index_col='utc-timestamp', parse_dates=True) for path in paths_to_input ] - return sum(all_ts).loc[:, country_codes] + return sum(all_ts) def create_regional_timeseries( paths_to_input: list[str], - country_codes: list[str], region_country_mapping: str, population: str, ) -> pd.DataFrame: @@ -30,7 +29,7 @@ def create_regional_timeseries( ASSUME all road transport is subnationally distributed in proportion to population. """ - df_national = create_national_timeseries(paths_to_input, country_codes) + df_national = create_national_timeseries(paths_to_input) region_country_mapping = ( pd.read_csv(region_country_mapping, index_col=0) @@ -66,17 +65,16 @@ def create_regional_timeseries( if __name__ == "__main__": resolution=snakemake.wildcards.resolution paths_to_input=snakemake.input.time_series - country_codes=[pycountry.countries.lookup(c).alpha_3 for c in snakemake.params.countries] path_to_output=snakemake.output[0] path_to_locations=snakemake.input.locations path_to_populations=snakemake.input.populations if resolution == "continental": - ts = create_continental_timeseries(paths_to_input, country_codes) + ts = create_continental_timeseries(paths_to_input) elif resolution == "national": - ts = create_national_timeseries(paths_to_input, country_codes) + ts = create_national_timeseries(paths_to_input) elif resolution == "regional": - ts = create_regional_timeseries(paths_to_input, country_codes, path_to_locations, path_to_populations) + ts = create_regional_timeseries(paths_to_input, path_to_locations, path_to_populations) else: raise ValueError("Input resolution not recognised.") diff --git a/scripts/transport/jrc_idees.py b/scripts/transport/jrc_idees.py index ddcb76ae..99659f85 100644 --- a/scripts/transport/jrc_idees.py +++ b/scripts/transport/jrc_idees.py @@ -39,7 +39,7 @@ } -def process_jrc_transport_data(paths_to_data: list[str], dataset: object, out_path: str): +def process_jrc_transport_data(paths_to_data: list[str], dataset: object, out_path: str, vehicle_type_names: dict[str, str]) -> None: paths_to_data = [Path(p) for p in paths_to_data] processed_data = pd.concat([ read_transport_excel(path, **DATASET_PARAMS[dataset]) @@ -54,10 +54,10 @@ def process_jrc_transport_data(paths_to_data: list[str], dataset: object, out_pa .set_index("country_code", append=True) .stack('year') .rename('value') + .rename(index = vehicle_type_names, level = 'vehicle_type') .to_csv(out_path) ) - processed_data def read_transport_excel(path: Path, @@ -176,5 +176,6 @@ def remove_of_which(df: pd.DataFrame, main_carrier: str, of_which_carrier: str) process_jrc_transport_data( paths_to_data=snakemake.input.data, dataset=snakemake.wildcards.dataset, - out_path=snakemake.output[0] + out_path=snakemake.output[0], + vehicle_type_names={v:k for k,v in snakemake.params.vehicle_type_names.items()}, ) diff --git a/scripts/transport/road_transport_timeseries.py b/scripts/transport/road_transport_timeseries.py index 4c75517d..a075cf91 100644 --- a/scripts/transport/road_transport_timeseries.py +++ b/scripts/transport/road_transport_timeseries.py @@ -1,52 +1,83 @@ import pandas as pd - +import pycountry def create_road_transport_demand_timeseries( - path_to_input: str, first_year: int, final_year: int, type_name: str, - power_scaling_factor: float, conversion_factor: float, historic: bool, path_to_output: str + path_to_annual_data: str, path_to_timeseries: str, first_year: int, final_year: int, vehicle_type: str, country_neighbour_dict: dict[str, list[str]], + power_scaling_factor: float, conversion_factor: float, historic: bool, country_codes: list[str], path_to_output: str ) -> None: + # Read annual road transport distance into panda dataframe - df = pd.read_csv(path_to_input, index_col=[0, 1, 2]) - - # ASSUME: Every hour of the year the same amount of distance gets driven. - # Calculate the distance travelled per hour - series = df["value"] / 8760 + df_annual = ( + pd + .read_csv(path_to_annual_data, index_col=[0, 1, 2], parse_dates=[2]) + .squeeze() + .xs(vehicle_type) + .xs(slice(str(first_year), str(final_year + 1)), level="year", drop_level=False) + .unstack("country_code") + .tz_localize('UTC') + .resample('H') + .ffill() + .iloc[:-1] + ) - # Process the road transport distance timeseries - create_timeseries(type_name, power_scaling_factor, conversion_factor, first_year, - final_year, series, path_to_output, historic=historic) + # TODO check if path_to_timeseries data is charging demand or transport demand + if vehicle_type in ["passenger-cars","motorcycles","light-duty-vehicles"]: + df_timeseries = ( + pd + .read_csv(path_to_timeseries, index_col=[0, 1, 2], parse_dates=[0]) + .xs(slice(first_year, final_year), level="year") + .unstack("country_code") + .droplevel(level = 0, axis = "columns") + .groupby(by = lambda idx: idx.year) + .transform(lambda x: x/x.sum()) + .pipe(fill_empty_country, country_neighbour_dict) + .mul(df_annual) + ) -def create_timeseries(vehicle: str, power_scaling_factor: float, conversion_factor: float, - first_year: int, final_year: int, series: pd.Series, - output_path: str, historic: bool): - ts_index = pd.to_datetime(range(first_year, final_year + 2), format="%Y") - ts = ( - series - .xs(vehicle) - .xs(slice(first_year, final_year + 1), level=1, drop_level=False) - .unstack("country_code") - .set_index(ts_index) - .resample("H") - .ffill() - .iloc[:-1] # remove first hour in following year + elif vehicle_type in ["heavy-duty-vehicles","coaches-and-buses"]: + # ASSUME heavy transport profiles are flat + df_timeseries = ( + df_annual + .groupby(by = lambda idx: idx.year) + .transform(lambda x: x/ len(x.index)) + ) + + else: + raise ValueError(f"vehicle_type {vehicle_type} is not supported") + + df_timeseries = ( + df_timeseries .mul(conversion_factor) .mul(power_scaling_factor) .mul(1 if historic else -1) # historic demand is actually a supply to avoid double counting + .loc[:, country_codes] + .tz_localize(None) + .rename_axis("utc-timestamp") ) - ts_index = pd.to_datetime(ts.index, format="%Y") - ts = ts.set_index(ts_index) - ts.to_csv(output_path, index_label="utc-timestamp") + assert df_timeseries.isna().any(axis = None) == False, "There are NaN values in the timeseries dataframe" + df_timeseries.to_csv(path_to_output) + + +def fill_empty_country(df, country_neighbour_dict): + for country, neighbours in country_neighbour_dict.items(): + assert country not in df.columns + df[country] = df[neighbours].mean(axis=1) + return df if __name__ == "__main__": create_road_transport_demand_timeseries( - path_to_input=snakemake.input.data, + path_to_annual_data=snakemake.input.annual_data, + path_to_timeseries=snakemake.input.timeseries, power_scaling_factor=snakemake.params.power_scaling_factor, first_year=snakemake.params.first_year, final_year=snakemake.params.final_year, - type_name=snakemake.params.type_name, + vehicle_type=snakemake.wildcards.vehicle_type, conversion_factor=snakemake.params.conversion_factor, historic=snakemake.params.historic, path_to_output=snakemake.output[0], + country_codes=[pycountry.countries.lookup(c).alpha_3 for c in snakemake.params.countries], + country_neighbour_dict={'ALB': ['HRV'], 'MKD': ['HRV'], 'GRC': ['ROU'], 'BGR': ['ROU'], + 'BIH': ['HRV', 'HUN'], 'MNE': ['HRV'], 'SRB': ['HUN']}, ) From 79b83c9936a42bff3c3bf173ffa13f6b7dc307b1 Mon Sep 17 00:00:00 2001 From: adrienmellot Date: Wed, 13 Mar 2024 15:27:25 +0100 Subject: [PATCH 2/3] Add fill-missing-values as parameters for timeseries --- config/default.yaml | 23 ++++++++---- config/schema.yaml | 35 ++++++++++++++----- rules/transport.smk | 4 ++- .../transport/road_transport_timeseries.py | 3 +- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/config/default.yaml b/config/default.yaml index 12d4add0..573ab7cf 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -142,13 +142,22 @@ parameters: passenger-cars: Passenger cars motorcycles: Powered 2-wheelers fill-missing-values: - ALB: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] - BIH: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] - MNE: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] - MKD: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] - SRB: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] - NOR: ['SWE', 'DNK'] - CHE: ['DEU', 'AUT', 'FRA', 'ITA'] + annual-data: + ALB: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] + BIH: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] + MNE: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] + MKD: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] + SRB: ['BGR', 'HRV', 'HUN', 'ROU', 'GRC'] + NOR: ['SWE', 'DNK'] + CHE: ['DEU', 'AUT', 'FRA', 'ITA'] + timeseries-data: + ALB: ['HRV'] + MKD: ['HRV'] + GRC: ['ROU'] + BGR: ['ROU'] + BIH: ['HRV', 'HUN'] + MNE: ['HRV'] + SRB: ['HUN'] entsoe-tyndp: scenario: National Trends grid: Reference diff --git a/config/schema.yaml b/config/schema.yaml index 794acfa0..7391321a 100644 --- a/config/schema.yaml +++ b/config/schema.yaml @@ -307,17 +307,34 @@ properties: type: string description: JRC-IDEES name of motorcycles. fill-missing-values: - description: Fill missing values in annual transport demand. type: object + description: Dictionaries to fill missing values additionalProperties: false - patternProperties: - "^[A-Z][A-Z][A-Z]$": - type: array - description: Country to fill missing values for. - items: - type: string - pattern: ^[A-Z][A-Z][A-Z]$ - description: Country to fill missing values from. + properties: + annual-data: + description: Fill missing values in annual transport demand. + type: object + additionalProperties: false + patternProperties: + "^[A-Z][A-Z][A-Z]$": + type: array + description: Country to fill missing values for. + items: + type: string + pattern: ^[A-Z][A-Z][A-Z]$ + description: Country to fill missing values from. + timeseries-data: + description: Fill missing countries in timeseries profile. + type: object + additionalProperties: false + patternProperties: + "^[A-Z][A-Z][A-Z]$": + type: array + description: Country to fill missing values for. + items: + type: string + pattern: ^[A-Z][A-Z][A-Z]$ + description: Country to fill missing values from. entsoe-tyndp: type: object description: Parameters to define scenario choice for data accessed from the ENTSO-E ten-year network development plan 2020. For more information, see https://2020.entsos-tyndp-scenarios.eu/ diff --git a/rules/transport.smk b/rules/transport.smk index e084bfcb..2960356b 100644 --- a/rules/transport.smk +++ b/rules/transport.smk @@ -17,7 +17,7 @@ rule annual_transport_demand: jrc_road_distance = "build/data/jrc-idees/transport/processed-road-distance.csv", jrc_road_vehicles = "build/data/jrc-idees/transport/processed-road-vehicles.csv", params: - fill_missing_values = config["parameters"]["transport"]["fill-missing-values"], + fill_missing_values = config["parameters"]["transport"]["fill-missing-values"]["annual-data"], efficiency_quantile = config["parameters"]["transport"]["future-vehicle-efficiency-percentile"] conda: "../envs/default.yaml" output: @@ -40,6 +40,7 @@ rule create_road_transport_timeseries: conversion_factor = lambda wildcards: config["parameters"]["transport"]["road-transport-conversion-factors"][wildcards.vehicle_type], historic = False, countries = config["scope"]["spatial"]["countries"], + country_neighbour_dict= config["parameters"]["transport"]["fill-missing-values"]["timeseries-data"], conda: "../envs/default.yaml" wildcard_constraints: vehicle_type = "light-duty-vehicles|heavy-duty-vehicles|coaches-and-buses|passenger-cars|motorcycles" @@ -60,6 +61,7 @@ use rule create_road_transport_timeseries as create_road_transport_timeseries_hi conversion_factor = lambda wildcards: config["parameters"]["transport"]["road-transport-conversion-factors"][wildcards.vehicle_type], historic = True, countries = config["scope"]["spatial"]["countries"], + country_neighbour_dict= config["parameters"]["transport"]["fill-missing-values"]["timeseries-data"], output: "build/data/transport/timeseries/timeseries-{vehicle_type}-historic-electrification.csv" diff --git a/scripts/transport/road_transport_timeseries.py b/scripts/transport/road_transport_timeseries.py index a075cf91..be3c764f 100644 --- a/scripts/transport/road_transport_timeseries.py +++ b/scripts/transport/road_transport_timeseries.py @@ -78,6 +78,5 @@ def fill_empty_country(df, country_neighbour_dict): historic=snakemake.params.historic, path_to_output=snakemake.output[0], country_codes=[pycountry.countries.lookup(c).alpha_3 for c in snakemake.params.countries], - country_neighbour_dict={'ALB': ['HRV'], 'MKD': ['HRV'], 'GRC': ['ROU'], 'BGR': ['ROU'], - 'BIH': ['HRV', 'HUN'], 'MNE': ['HRV'], 'SRB': ['HUN']}, + country_neighbour_dict=snakemake.params.country_neighbour_dict, ) From 5a925336b05ef72971753499600200c5f8e7394f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Tr=C3=B6ndle?= Date: Fri, 15 Mar 2024 10:24:10 +0100 Subject: [PATCH 3/3] Update comments --- scripts/transport/road_transport_timeseries.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/transport/road_transport_timeseries.py b/scripts/transport/road_transport_timeseries.py index be3c764f..a64eeaae 100644 --- a/scripts/transport/road_transport_timeseries.py +++ b/scripts/transport/road_transport_timeseries.py @@ -5,7 +5,7 @@ def create_road_transport_demand_timeseries( path_to_annual_data: str, path_to_timeseries: str, first_year: int, final_year: int, vehicle_type: str, country_neighbour_dict: dict[str, list[str]], power_scaling_factor: float, conversion_factor: float, historic: bool, country_codes: list[str], path_to_output: str ) -> None: - + # Read annual road transport distance into panda dataframe df_annual = ( pd @@ -20,9 +20,9 @@ def create_road_transport_demand_timeseries( .iloc[:-1] ) - # TODO check if path_to_timeseries data is charging demand or transport demand - if vehicle_type in ["passenger-cars","motorcycles","light-duty-vehicles"]: + # Use RAMP time series profiles for small and light vehicles. + # TODO check if path_to_timeseries data is charging demand or transport demand df_timeseries = ( pd .read_csv(path_to_timeseries, index_col=[0, 1, 2], parse_dates=[0]) @@ -36,16 +36,16 @@ def create_road_transport_demand_timeseries( ) elif vehicle_type in ["heavy-duty-vehicles","coaches-and-buses"]: - # ASSUME heavy transport profiles are flat + # ASSUME flat profiles for heavy transport. df_timeseries = ( df_annual .groupby(by = lambda idx: idx.year) .transform(lambda x: x/ len(x.index)) ) - + else: raise ValueError(f"vehicle_type {vehicle_type} is not supported") - + df_timeseries = ( df_timeseries .mul(conversion_factor)