diff --git a/.github/workflows/update-fixed-env.yaml b/.github/workflows/update-fixed-env.yaml new file mode 100644 index 00000000..f66890aa --- /dev/null +++ b/.github/workflows/update-fixed-env.yaml @@ -0,0 +1,39 @@ +name: Fixed Environment YAML Monitor + +on: + push: + branches: + - master + paths: + - 'env/environment.yaml' + +jobs: + update_environment_fixed: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Setup micromamba + uses: mamba-org/setup-micromamba@v1 + with: + micromamba-version: latest + environment-file: envs/environment.yaml + log-level: debug + init-shell: bash + cache-environment: true + cache-downloads: true + + - name: Update environment.fixed.yaml + run: | + mamba env export --file envs/environment.fixed.yaml --no-builds + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 + with: + token: ${{ secrets.GITHUB_TOKEN }} + branch: update-environment-fixed + title: Update fixed environment + body: Automatically generated PR to update environment.fixed.yaml + labels: automated diff --git a/data/GDP_PPP_30arcsec_v3_mapped_default.csv b/data/GDP_PPP_30arcsec_v3_mapped_default.csv deleted file mode 100644 index f0e640b3..00000000 --- a/data/GDP_PPP_30arcsec_v3_mapped_default.csv +++ /dev/null @@ -1,151 +0,0 @@ -name,GDP_PPP,country -3140,632728.0438507323,MD -3139,806541.9318093687,MD -3142,1392454.6690911907,MD -3152,897871.2903553953,MD -3246,645554.8588933202,MD -7049,1150156.4449477682,MD -1924,162285.16792916053,UA -1970,751970.6071848695,UA -2974,368873.75840156944,UA -2977,294847.85539198935,UA -2979,197988.13680768458,UA -2980,301371.2491126519,UA -3031,56925.21878805953,UA -3032,139395.18279351242,UA -3033,145377.8061037629,UA -3035,52282.83655208812,UA -3036,497950.25890516065,UA -3037,1183293.1987702171,UA -3038,255005.98207636533,UA -3039,224711.50098325178,UA -3040,342959.943226467,UA -3044,69119.31486955672,UA -3045,246273.65986119965,UA -3047,146742.08407299497,UA -3049,107265.7028733467,UA -3050,1126147.985259493,UA -3051,69833.56303043803,UA -3052,67230.88206577855,UA -3053,27019.224685201345,UA -3054,260571.47337292184,UA -3055,88760.94152915622,UA -3056,101368.26196568517,UA -3058,55752.92329667119,UA -3059,89024.37880630122,UA -3062,358411.291265149,UA -3064,75081.64142862396,UA -3065,158101.42949135564,UA -3066,83763.89576442329,UA -3068,173474.51218344545,UA -3069,60327.01572375589,UA -3070,18073.687271955278,UA -3071,249069.43314695224,UA -3072,220707.35700825177,UA -3073,61342.30137462664,UA -3074,254235.98867635374,UA -3077,769558.9832370486,UA -3078,132674.2315809836,UA -3079,1388517.1478032232,UA -3080,1861003.8718246964,UA -3082,140123.73854745473,UA -3083,834887.5595419679,UA -3084,1910795.5590558557,UA -3086,93828.36549170096,UA -3088,347197.65113392205,UA -3089,3754718.141734592,UA -3090,521912.69768585655,UA -3093,232818.05269714879,UA -3095,435376.20361377904,UA -3099,345596.5288937008,UA -3100,175689.10947424968,UA -3105,538438.9311459162,UA -3107,88096.86032871014,UA -3108,79847.68447063807,UA -3109,348504.73449373,UA -3144,71657.0165675802,UA -3146,80342.05037424155,UA -3158,74465.12922576343,UA -3164,3102112.2672631275,UA -3165,65215.04081671433,UA -3166,413924.2225725632,UA -3167,135060.0056434935,UA -3168,54980.442979330146,UA -3170,29584.879122227037,UA -3171,142780.68163047134,UA -3172,40436.63814695243,UA -3173,1253342.1790126422,UA -3174,173842.03139155387,UA -3176,65699.76352408895,UA -3177,143591.75419817626,UA -3178,56434.04525832523,UA -3179,389996.1670051216,UA -3180,138452.84503524794,UA -3181,67402.59500436619,UA -3184,51204.293695376415,UA -3185,46867.82356528432,UA -3186,103892.35612417295,UA -3187,193668.91476930346,UA -3189,54584.176457692694,UA -3190,219077.64942830536,UA -3197,88516.52699983507,UA -3198,298166.8272673622,UA -3199,61334.952541812374,UA -3229,175692.61136747137,UA -3230,106722.62773321665,UA -3236,61542.06264321315,UA -3241,83752.90489164277,UA -4301,48419.52825967164,UA -4305,147759.74280349456,UA -4306,53156.905740992224,UA -4315,218025.78516351627,UA -4317,155240.40554731718,UA -4318,1342144.2459407183,UA -4319,91669.1449633853,UA -4321,85852.49282415409,UA -4347,67938.7698430624,UA -4357,20064.979012172935,UA -4360,47840.51245168512,UA -4361,55580.924388032574,UA -4362,165753.82588729708,UA -4363,46390.2448142152,UA -4365,96265.47592938849,UA -4366,272003.25510057947,UA -4367,80878.50229245829,UA -4370,330072.35444044066,UA -4371,7707066.181975477,UA -4373,2019766.7891575783,UA -4374,985354.331818515,UA -4377,230805.08833664874,UA -4382,125670.67125287943,UA -4383,46914.065511740075,UA -4384,48020.804310510954,UA -4385,55612.34707641123,UA -4387,74558.3475791577,UA -4388,245243.33449409154,UA -4389,95696.56767732685,UA -4391,251085.7523045193,UA -4401,66375.82996856027,UA -4403,111954.41038437477,UA -4405,46911.68560148837,UA -4408,150782.51691456966,UA -4409,112776.7399582134,UA -4410,153076.56860965435,UA -4412,192629.31238456024,UA -4413,181295.3120834606,UA -4414,995694.9413199169,UA -4416,157640.7868989174,UA -4418,77580.20674809469,UA -4420,122320.99275223716,UA -4424,184891.10924920067,UA -4425,84486.75974340564,UA -4431,50485.84380961137,UA -4435,231040.45446464577,UA -4436,81222.18707585508,UA -4438,114819.76472988473,UA -4439,76839.1052178896,UA -4440,135337.0313562152,UA -4441,49159.485269198034,UA -7031,42001.73757065917,UA -7059,159790.48382874,UA -7063,39599.10564971086,UA diff --git a/doc/configtables/sector.csv b/doc/configtables/sector.csv index 059c4233..5045cecd 100644 --- a/doc/configtables/sector.csv +++ b/doc/configtables/sector.csv @@ -5,7 +5,7 @@ biomass,--,"{true, false}",Flag to include biomass sector. industry,--,"{true, false}",Flag to include industry sector. agriculture,--,"{true, false}",Flag to include agriculture sector. district_heating,--,,`prepare_sector_network.py `_ --- potential,--,float,maximum fraction of urban demand which can be supplied by district heating +-- potential,--,float,maximum fraction of urban demand which can be supplied by district heating. Ignored where below current fraction. -- progress,--,Dictionary with planning horizons as keys., Increase of today's district heating demand to potential maximum district heating share. Progress = 0 means today's district heating share. Progress = 1 means maximum fraction of urban demand is supplied by district heating -- district_heating_loss,--,float,Share increase in district heat demand in urban central due to heat losses cluster_heat_buses,--,"{true, false}",Cluster residential and service heat buses in `prepare_sector_network.py `_ to one to save memory. diff --git a/doc/release_notes.rst b/doc/release_notes.rst index cf0f2c76..eb29ce4b 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -31,6 +31,16 @@ Upcoming Release * Bugfix: Correctly read in threshold capacity below which to remove components from previous planning horizons in :mod:`add_brownfield`. +* For countries not contained in the NUTS3-specific datasets (i.e. MD and UA), the mapping of GDP per capita and population per bus region used to spatially distribute electricity demand is now endogenised in a new rule :mod:`build_gdp_ppp_non_nuts3`. https://github.com/PyPSA/pypsa-eur/pull/1146 + +* The databundle has been updated to release v0.3.0, which includes raw GDP and population data for countries outside the NUTS system (UA, MD). https://github.com/PyPSA/pypsa-eur/pull/1146 + +* Updated filtering in :mod:`determine_availability_matrix_MD_UA.py` to improve speed. https://github.com/PyPSA/pypsa-eur/pull/1146 + +* Bugfix: Impose minimum value of zero for district heating progress between current and future market share in :mod:`build_district_heat_share`. + +* Enable parallelism in :mod:`determine_availability_matrix_MD_UA.py` and remove plots. This requires the use of temporary files. + PyPSA-Eur 0.11.0 (25th May 2024) ===================================== diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index eff0d9e0..18ff8230 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -202,7 +202,6 @@ rule determine_availability_matrix_MD_UA: + ".nc", output: availability_matrix=resources("availability_matrix_MD-UA_{technology}.nc"), - availability_map=resources("availability_matrix_MD-UA_{technology}.png"), log: logs("determine_availability_matrix_MD_UA_{technology}.log"), threads: config["atlite"].get("nprocesses", 4) @@ -375,6 +374,37 @@ def input_conventional(w): } +# Optional input when having Ukraine (UA) or Moldova (MD) in the countries list +def input_gdp_pop_non_nuts3(w): + countries = set(config_provider("countries")(w)) + if {"UA", "MD"}.intersection(countries): + return {"gdp_pop_non_nuts3": resources("gdp_pop_non_nuts3.geojson")} + return {} + + +rule build_gdp_pop_non_nuts3: + params: + countries=config_provider("countries"), + input: + base_network=resources("networks/base.nc"), + regions=resources("regions_onshore.geojson"), + gdp_non_nuts3="data/bundle/GDP_per_capita_PPP_1990_2015_v2.nc", + pop_non_nuts3="data/bundle/ppp_2013_1km_Aggregated.tif", + output: + resources("gdp_pop_non_nuts3.geojson"), + log: + logs("build_gdp_pop_non_nuts3.log"), + benchmark: + benchmarks("build_gdp_pop_non_nuts3") + threads: 1 + resources: + mem_mb=8000, + conda: + "../envs/environment.yaml" + script: + "../scripts/build_gdp_pop_non_nuts3.py" + + rule add_electricity: params: length_factor=config_provider("lines", "length_factor"), @@ -390,6 +420,7 @@ rule add_electricity: input: unpack(input_profile_tech), unpack(input_conventional), + unpack(input_gdp_pop_non_nuts3), base_network=resources("networks/base.nc"), line_rating=lambda w: ( resources("networks/line_rating.nc") @@ -411,7 +442,6 @@ rule add_electricity: ), load=resources("electricity_demand.csv"), nuts3_shapes=resources("nuts3_shapes.geojson"), - ua_md_gdp="data/GDP_PPP_30arcsec_v3_mapped_default.csv", output: resources("networks/elec.nc"), log: diff --git a/rules/common.smk b/rules/common.smk index 2b8495e1..ef518beb 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -55,7 +55,7 @@ def dynamic_getter(wildcards, keys, default): scenario_name = wildcards.run if scenario_name not in scenarios: raise ValueError( - f"Scenario {scenario_name} not found in file {config['run']['scenario']['file']}." + f"Scenario {scenario_name} not found in file {config['run']['scenarios']['file']}." ) config_with_scenario = scenario_config(scenario_name) config_with_wildcards = update_config_from_wildcards( @@ -81,7 +81,8 @@ def config_provider(*keys, default=None): def solver_threads(w): solver_options = config_provider("solving", "solver_options")(w) option_set = config_provider("solving", "solver", "options")(w) - threads = solver_options[option_set].get("threads", 4) + solver_option_set = solver_options[option_set] + threads = solver_option_set.get("threads") or solver_option_set.get("Threads") or 4 return threads diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 5b0871ca..24e387c5 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -29,6 +29,8 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_databundle", "h2_salt_caverns_GWh_per_sqkm.geojson", "natura/natura.tiff", "gebco/GEBCO_2014_2D.nc", + "GDP_per_capita_PPP_1990_2015_v2.nc", + "ppp_2013_1km_Aggregated.tif", ] rule retrieve_databundle: @@ -172,7 +174,7 @@ if config["enable"]["retrieve"]: rule retrieve_ship_raster: input: storage( - "https://zenodo.org/records/10973944/files/shipdensity_global.zip", + "https://zenodo.org/records/12760663/files/shipdensity_global.zip", keep_local=True, ), output: diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index f90d6c85..17e030b4 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -294,19 +294,19 @@ def shapes_to_shapes(orig, dest): return transfer -def attach_load(n, regions, load, nuts3_shapes, ua_md_gdp, countries, scaling=1.0): +def attach_load( + n, regions, load, nuts3_shapes, gdp_pop_non_nuts3, countries, scaling=1.0 +): substation_lv_i = n.buses.index[n.buses["substation_lv"]] - regions = gpd.read_file(regions).set_index("name").reindex(substation_lv_i) + gdf_regions = gpd.read_file(regions).set_index("name").reindex(substation_lv_i) opsd_load = pd.read_csv(load, index_col=0, parse_dates=True).filter(items=countries) - ua_md_gdp = pd.read_csv(ua_md_gdp, dtype={"name": "str"}).set_index("name") - logger.info(f"Load data scaled by factor {scaling}.") opsd_load *= scaling nuts3 = gpd.read_file(nuts3_shapes).set_index("index") - def upsample(cntry, group): + def upsample(cntry, group, gdp_pop_non_nuts3): load = opsd_load[cntry] if len(group) == 1: @@ -325,7 +325,15 @@ def attach_load(n, regions, load, nuts3_shapes, ua_md_gdp, countries, scaling=1. factors = normed(0.6 * normed(gdp_n) + 0.4 * normed(pop_n)) if cntry in ["UA", "MD"]: # overwrite factor because nuts3 provides no data for UA+MD - factors = normed(ua_md_gdp.loc[group.index, "GDP_PPP"].squeeze()) + gdp_pop_non_nuts3 = gpd.read_file(gdp_pop_non_nuts3).set_index("Bus") + gdp_pop_non_nuts3 = gdp_pop_non_nuts3.loc[ + (gdp_pop_non_nuts3.country == cntry) + & (gdp_pop_non_nuts3.index.isin(substation_lv_i)) + ] + factors = normed( + 0.6 * normed(gdp_pop_non_nuts3["gdp"]) + + 0.4 * normed(gdp_pop_non_nuts3["pop"]) + ) return pd.DataFrame( factors.values * load.values[:, np.newaxis], index=load.index, @@ -334,8 +342,8 @@ def attach_load(n, regions, load, nuts3_shapes, ua_md_gdp, countries, scaling=1. load = pd.concat( [ - upsample(cntry, group) - for cntry, group in regions.geometry.groupby(regions.country) + upsample(cntry, group, gdp_pop_non_nuts3) + for cntry, group in gdf_regions.geometry.groupby(gdf_regions.country) ], axis=1, ) @@ -821,7 +829,7 @@ if __name__ == "__main__": snakemake.input.regions, snakemake.input.load, snakemake.input.nuts3_shapes, - snakemake.input.ua_md_gdp, + snakemake.input.get("gdp_pop_non_nuts3"), params.countries, params.scaling_factor, ) diff --git a/scripts/build_district_heat_share.py b/scripts/build_district_heat_share.py index d62d2ab0..7e8497d6 100644 --- a/scripts/build_district_heat_share.py +++ b/scripts/build_district_heat_share.py @@ -86,7 +86,7 @@ if __name__ == "__main__": urban_fraction = pd.concat([urban_fraction, dist_fraction_node], axis=1).max(axis=1) # difference of max potential and today's share of district heating - diff = (urban_fraction * central_fraction) - dist_fraction_node + diff = ((urban_fraction * central_fraction) - dist_fraction_node).clip(lower=0) progress = get( snakemake.config["sector"]["district_heating"]["progress"], investment_year ) diff --git a/scripts/build_gdp_pop_non_nuts3.py b/scripts/build_gdp_pop_non_nuts3.py new file mode 100644 index 00000000..d475aec9 --- /dev/null +++ b/scripts/build_gdp_pop_non_nuts3.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Maps the per-capita GDP and population values to non-NUTS3 regions. + +The script takes as input the country code, a GeoDataFrame containing +the regions, and the file paths to the datasets containing the GDP and +POP values for non-NUTS3 countries. +""" + +import logging + +import geopandas as gpd +import numpy as np +import pandas as pd +import pypsa +import rasterio +import xarray as xr +from _helpers import configure_logging, set_scenario_config +from rasterio.mask import mask +from shapely.geometry import box + +logger = logging.getLogger(__name__) + + +def calc_gdp_pop(country, regions, gdp_non_nuts3, pop_non_nuts3): + """ + Calculate the GDP p.c. and population values for non NUTS3 regions. + + Parameters: + country (str): The two-letter country code of the non-NUTS3 region. + regions (GeoDataFrame): A GeoDataFrame containing the regions. + gdp_non_nuts3 (str): The file path to the dataset containing the GDP p.c values + for non NUTS3 countries (e.g. MD, UA) + pop_non_nuts3 (str): The file path to the dataset containing the POP values + for non NUTS3 countries (e.g. MD, UA) + + Returns: + tuple: A tuple containing two GeoDataFrames: + - gdp: A GeoDataFrame with the mean GDP p.c. values mapped to each bus. + - pop: A GeoDataFrame with the summed POP values mapped to each bus. + """ + regions = ( + regions.rename(columns={"name": "Bus"}) + .drop(columns=["x", "y"]) + .set_index("Bus") + ) + regions = regions[regions.country == country] + # Create a bounding box for UA, MD from region shape, including a buffer of 10000 metres + bounding_box = ( + gpd.GeoDataFrame(geometry=[box(*regions.total_bounds)], crs=regions.crs) + .to_crs(epsg=3857) + .buffer(10000) + .to_crs(regions.crs) + ) + + # GDP Mapping + logger.info(f"Mapping mean GDP p.c. to non-NUTS3 region: {country}") + with xr.open_dataset(gdp_non_nuts3) as src_gdp: + src_gdp = src_gdp.where( + (src_gdp.longitude >= bounding_box.bounds.minx.min()) + & (src_gdp.longitude <= bounding_box.bounds.maxx.max()) + & (src_gdp.latitude >= bounding_box.bounds.miny.min()) + & (src_gdp.latitude <= bounding_box.bounds.maxy.max()), + drop=True, + ) + gdp = src_gdp.to_dataframe().reset_index() + gdp = gdp.rename(columns={"GDP_per_capita_PPP": "gdp"}) + gdp = gdp[gdp.time == gdp.time.max()] + gdp_raster = gpd.GeoDataFrame( + gdp, + geometry=gpd.points_from_xy(gdp.longitude, gdp.latitude), + crs="EPSG:4326", + ) + gdp_mapped = gpd.sjoin(gdp_raster, regions, predicate="within") + gdp = ( + gdp_mapped.copy() + .groupby(["Bus", "country"]) + .agg({"gdp": "mean"}) + .reset_index(level=["country"]) + ) + + # Population Mapping + logger.info(f"Mapping summed population to non-NUTS3 region: {country}") + with rasterio.open(pop_non_nuts3) as src_pop: + # Mask the raster with the bounding box + out_image, out_transform = mask(src_pop, bounding_box, crop=True) + out_meta = src_pop.meta.copy() + out_meta.update( + { + "driver": "GTiff", + "height": out_image.shape[1], + "width": out_image.shape[2], + "transform": out_transform, + } + ) + masked_data = out_image[0] # Use the first band (rest is empty) + row_indices, col_indices = np.where(masked_data != src_pop.nodata) + values = masked_data[row_indices, col_indices] + + # Affine transformation from pixel coordinates to geo coordinates + x_coords, y_coords = rasterio.transform.xy(out_transform, row_indices, col_indices) + pop_raster = pd.DataFrame({"x": x_coords, "y": y_coords, "pop": values}) + pop_raster = gpd.GeoDataFrame( + pop_raster, + geometry=gpd.points_from_xy(pop_raster.x, pop_raster.y), + crs=src_pop.crs, + ) + pop_mapped = gpd.sjoin(pop_raster, regions, predicate="within") + pop = ( + pop_mapped.groupby(["Bus", "country"]) + .agg({"pop": "sum"}) + .reset_index() + .set_index("Bus") + ) + gdp_pop = regions.join(gdp.drop(columns="country"), on="Bus").join( + pop.drop(columns="country"), on="Bus" + ) + gdp_pop.fillna(0, inplace=True) + + return gdp_pop + + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake("build_gdp_pop_non_nuts3") + configure_logging(snakemake) + set_scenario_config(snakemake) + + n = pypsa.Network(snakemake.input.base_network) + regions = gpd.read_file(snakemake.input.regions) + + gdp_non_nuts3 = snakemake.input.gdp_non_nuts3 + pop_non_nuts3 = snakemake.input.pop_non_nuts3 + + subset = {"MD", "UA"}.intersection(snakemake.params.countries) + + gdp_pop = pd.concat( + [ + calc_gdp_pop(country, regions, gdp_non_nuts3, pop_non_nuts3) + for country in subset + ], + axis=0, + ) + + logger.info( + f"Exporting GDP and POP values for non-NUTS3 regions {snakemake.output}" + ) + gdp_pop.reset_index().to_file(snakemake.output, driver="GeoJSON") diff --git a/scripts/determine_availability_matrix_MD_UA.py b/scripts/determine_availability_matrix_MD_UA.py index 678ef025..0e7962ab 100644 --- a/scripts/determine_availability_matrix_MD_UA.py +++ b/scripts/determine_availability_matrix_MD_UA.py @@ -8,16 +8,15 @@ Create land elibility analysis for Ukraine and Moldova with different datasets. import functools import logging +import os import time +from tempfile import NamedTemporaryFile import atlite import fiona import geopandas as gpd -import matplotlib.pyplot as plt import numpy as np from _helpers import configure_logging, set_scenario_config -from atlite.gis import shape_availability -from rasterio.plot import show logger = logging.getLogger(__name__) @@ -40,7 +39,7 @@ if __name__ == "__main__": configure_logging(snakemake) set_scenario_config(snakemake) - nprocesses = None # snakemake.config["atlite"].get("nprocesses") + nprocesses = int(snakemake.threads) noprogress = not snakemake.config["atlite"].get("show_progress", True) config = snakemake.config["renewable"][snakemake.wildcards.technology] @@ -48,7 +47,9 @@ if __name__ == "__main__": regions = ( gpd.read_file(snakemake.input.regions).set_index("name").rename_axis("bus") ) - buses = regions.index + # Limit to "UA" and "MD" regions + buses = regions.loc[regions["country"].isin(["UA", "MD"])].index.values + regions = regions.loc[buses] excluder = atlite.ExclusionContainer(crs=3035, res=100) @@ -93,8 +94,15 @@ if __name__ == "__main__": bbox=regions.geometry, layer=layer, ).to_crs(3035) + + # temporary file needed for parallelization + with NamedTemporaryFile(suffix=".geojson", delete=False) as f: + plg_tmp_fn = f.name if not wdpa.empty: - excluder.add_geometry(wdpa.geometry) + wdpa[["geometry"]].to_file(plg_tmp_fn) + while not os.path.exists(plg_tmp_fn): + time.sleep(1) + excluder.add_geometry(plg_tmp_fn) layer = get_wdpa_layer_name(wdpa_fn, "points") wdpa_pts = gpd.read_file( @@ -107,8 +115,15 @@ if __name__ == "__main__": wdpa_pts = wdpa_pts.set_geometry( wdpa_pts["geometry"].buffer(wdpa_pts["buffer_radius"]) ) + + # temporary file needed for parallelization + with NamedTemporaryFile(suffix=".geojson", delete=False) as f: + pts_tmp_fn = f.name if not wdpa_pts.empty: - excluder.add_geometry(wdpa_pts.geometry) + wdpa_pts[["geometry"]].to_file(pts_tmp_fn) + while not os.path.exists(pts_tmp_fn): + time.sleep(1) + excluder.add_geometry(pts_tmp_fn) if "max_depth" in config: # lambda not supported for atlite + multiprocessing @@ -144,16 +159,10 @@ if __name__ == "__main__": else: availability = cutout.availabilitymatrix(regions, excluder, **kwargs) - regions_geometry = regions.to_crs(3035).geometry - band, transform = shape_availability(regions_geometry, excluder) - fig, ax = plt.subplots(figsize=(4, 8)) - gpd.GeoSeries(regions_geometry.union_all()).plot(ax=ax, color="none") - show(band, transform=transform, cmap="Greens", ax=ax) - plt.axis("off") - plt.savefig(snakemake.output.availability_map, bbox_inches="tight", dpi=500) + for fn in [pts_tmp_fn, plg_tmp_fn]: + if os.path.exists(fn): + os.remove(fn) - # Limit results only to buses for UA and MD - buses = regions.loc[regions["country"].isin(["UA", "MD"])].index.values availability = availability.sel(bus=buses) # Save and plot for verification diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 53b811aa..b86f9557 100644 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -688,7 +688,7 @@ def add_co2_tracking(n, costs, options): e_nom_extendable=True, e_nom_max=e_nom_max, capital_cost=options["co2_sequestration_cost"], - marginal_cost=0.1, + marginal_cost=-0.1, bus=sequestration_buses, lifetime=options["co2_sequestration_lifetime"], carrier="co2 sequestered", diff --git a/scripts/retrieve_databundle.py b/scripts/retrieve_databundle.py index e2736f63..63b71dd5 100644 --- a/scripts/retrieve_databundle.py +++ b/scripts/retrieve_databundle.py @@ -48,7 +48,7 @@ if __name__ == "__main__": configure_logging(snakemake) set_scenario_config(snakemake) - url = "https://zenodo.org/records/10973944/files/bundle.tar.xz" + url = "https://zenodo.org/records/12760663/files/bundle.tar.xz" tarball_fn = Path(f"{rootpath}/bundle.tar.xz") to_fn = Path(rootpath) / Path(snakemake.output[0]).parent.parent