diff --git a/Snakefile b/Snakefile index 767833df7..589471ef3 100644 --- a/Snakefile +++ b/Snakefile @@ -1013,6 +1013,7 @@ rule prepare_ports: rule prepare_airports: params: airport_sizing_factor=config["sector"]["airport_sizing_factor"], + airport_custom_data=config["custom_data"]["airports"], output: ports="data/airports.csv", # TODO move from data to resources script: diff --git a/config.default.yaml b/config.default.yaml index cd8850723..1580b1d4d 100644 --- a/config.default.yaml +++ b/config.default.yaml @@ -481,6 +481,7 @@ custom_data: custom_sectors: false gas_network: false # If "True" then a custom .csv file must be placed in "resources/custom_data/pipelines.csv" , If "False" the user can choose btw "greenfield" or Model built-in datasets. Please refer to ["sector"] below. export_ports: false # If "True" then a custom .csv file must be placed in "data/custom/export_ports.csv" + airports: false # If "True" then a custom .csv file must be placed in "data/custom/airports.csv". Data format for aiports must be in the format of the airports.csv file in the data folder. industry: reference_year: 2015 diff --git a/data/custom/airports.csv b/data/custom/airports.csv new file mode 100644 index 000000000..48ba06dd2 --- /dev/null +++ b/data/custom/airports.csv @@ -0,0 +1,2 @@ +,ident,type,airport_size_nr,name,y,x,elevation_ft,continent,country,iso_region,municipality,scheduled_service,iata_code,length_ft,width_ft,surface,lighted,closed,Total_airport_size_nr,fraction +0,5A8,medium_airport,1,Aleknagik / New Airport,59.2826004028,-158.617996216,66.0,,US,US-AK,Aleknagik,yes,WKK,2040.0,80.0,GRVL-DIRT-F,0.0,0.0,633,0.001579778830963665 diff --git a/scripts/prepare_airports.py b/scripts/prepare_airports.py index e69b20438..8762d0bc1 100644 --- a/scripts/prepare_airports.py +++ b/scripts/prepare_airports.py @@ -3,6 +3,9 @@ # # SPDX-License-Identifier: AGPL-3.0-or-later +import shutil +from pathlib import Path + import numpy as np import pandas as pd @@ -36,52 +39,10 @@ def download_airports(): return (airports_csv, runways_csv) -if __name__ == "__main__": - if "snakemake" not in globals(): - from _helpers import mock_snakemake - - snakemake = mock_snakemake("prepare_airports") - # configure_logging(snakemake) - - # run = snakemake.config.get("run", {}) - # RDIR = run["name"] + "/" if run.get("name") else "" - # store_path_data = Path.joinpath(Path().cwd(), "data") - # country_list = country_list_to_geofk(snakemake.config["countries"])' - - # Prepare downloaded data - airports_csv = download_airports()[0].copy() - airports_csv = airports_csv[ - [ - "ident", - "type", - "name", - "latitude_deg", - "longitude_deg", - "elevation_ft", - "continent", - "iso_country", - "iso_region", - "municipality", - "scheduled_service", - "iata_code", - ] - ] - airports_csv.loc[airports_csv["iso_country"].isnull(), "iso_country"] = "NA" - airports_csv = airports_csv.rename(columns={"latitude_deg": "y"}) - airports_csv = airports_csv.rename(columns={"longitude_deg": "x"}) - - runways_csv = download_airports()[1].copy() - runways_csv = runways_csv[ - ["airport_ident", "length_ft", "width_ft", "surface", "lighted", "closed"] - ] - runways_csv = runways_csv.drop_duplicates(subset=["airport_ident"]) - - airports_original = pd.merge( - airports_csv, runways_csv, how="left", left_on="ident", right_on="airport_ident" - ) - airports_original = airports_original.drop("airport_ident", axis=1) - - df = airports_original.copy() +def preprocess_airports(df): + """ + Preprocess the airports data + """ # Keep only airports that are of type medium and large df = df.loc[df["type"].isin(["large_airport", "medium_airport"])] @@ -117,5 +78,67 @@ def download_airports(): # Rename columns airports = airports.rename(columns={"iso_country": "country"}) - # Save - airports.to_csv(snakemake.output[0], sep=",", encoding="utf-8", header="true") + return airports + + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake("prepare_airports") + # configure_logging(snakemake) + + # run = snakemake.config.get("run", {}) + # RDIR = run["name"] + "/" if run.get("name") else "" + # store_path_data = Path.joinpath(Path().cwd(), "data") + # country_list = country_list_to_geofk(snakemake.config["countries"])' + + if snakemake.params.airport_custom_data: + custom_airports = Path.joinpath("data", "custom", "airports.csv") + shutil.move(custom_airports, snakemake.output[0]) + else: + # Prepare downloaded data + download_data = download_airports() + + airports_csv = download_data[0].copy() + airports_csv = airports_csv[ + [ + "ident", + "type", + "name", + "latitude_deg", + "longitude_deg", + "elevation_ft", + "continent", + "iso_country", + "iso_region", + "municipality", + "scheduled_service", + "iata_code", + ] + ] + airports_csv.loc[airports_csv["iso_country"].isnull(), "iso_country"] = "NA" + airports_csv = airports_csv.rename(columns={"latitude_deg": "y"}) + airports_csv = airports_csv.rename(columns={"longitude_deg": "x"}) + + runways_csv = download_data[1].copy() + runways_csv = runways_csv[ + ["airport_ident", "length_ft", "width_ft", "surface", "lighted", "closed"] + ] + runways_csv = runways_csv.drop_duplicates(subset=["airport_ident"]) + + airports_original = pd.merge( + airports_csv, + runways_csv, + how="left", + left_on="ident", + right_on="airport_ident", + ) + airports_original = airports_original.drop("airport_ident", axis=1) + + df = airports_original.copy() + + airports = preprocess_airports(df) + + # Save + airports.to_csv(snakemake.output[0], sep=",", encoding="utf-8", header="true") diff --git a/test/config.test_myopic.yaml b/test/config.test_myopic.yaml index 5fc393fde..b3b8d3b12 100644 --- a/test/config.test_myopic.yaml +++ b/test/config.test_myopic.yaml @@ -94,6 +94,8 @@ custom_data: custom_sectors: false gas_network: false # If "True" then a custom .csv file must be placed in "resources/custom_data/pipelines.csv" , If "False" the user can choose btw "greenfield" or Model built-in datasets. Please refer to ["sector"] below. export_ports: false # If "True" then a custom .csv file must be placed in "data/custom/export.csv" + airports: false # If "True" then a custom .csv file must be placed in "data/custom/airports.csv". Data format for aiports must be in the format of the airports.csv file in the data folder. + costs: # Costs used in PyPSA-Earth-Sec. Year depends on the wildcard planning_horizon in the scenario section