Merge branch 'master' into cluster-strategy-conventionals

This commit is contained in:
Fabian Hofmann 2022-06-20 18:23:02 +02:00 committed by GitHub
commit 8c704c024e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 76 additions and 31 deletions

View File

@ -70,6 +70,10 @@ Upcoming Release
* Use updated SARAH-2 and ERA5 cutouts with slightly wider scope to east and additional variables. * Use updated SARAH-2 and ERA5 cutouts with slightly wider scope to east and additional variables.
* Fix crs bug. Change crs 4236 to 4326.
* Update rasterio version to correctly calculate exclusion raster
PyPSA-Eur 0.4.0 (22th September 2021) PyPSA-Eur 0.4.0 (22th September 2021)
===================================== =====================================

View File

@ -24,7 +24,7 @@ dependencies:
- yaml - yaml
- pytables - pytables
- lxml - lxml
- powerplantmatching>=0.4.8 - powerplantmatching>=0.5.3
- numpy - numpy
- pandas - pandas
- geopandas - geopandas
@ -37,7 +37,7 @@ dependencies:
- pyomo - pyomo
- matplotlib - matplotlib
- proj - proj
- fiona <= 1.18.20 # Till issue https://github.com/Toblerity/Fiona/issues/1085 is not solved - fiona<=1.18.20 # Till issue https://github.com/Toblerity/Fiona/issues/1085 is not solved
# Keep in conda environment when calling ipython # Keep in conda environment when calling ipython
- ipython - ipython
@ -45,7 +45,7 @@ dependencies:
# GIS dependencies: # GIS dependencies:
- cartopy - cartopy
- descartes - descartes
- rasterio - rasterio<=1.2.9 # 1.2.10 creates error https://github.com/PyPSA/atlite/issues/238
# PyPSA-Eur-Sec Dependencies # PyPSA-Eur-Sec Dependencies
- geopy - geopy

View File

@ -240,7 +240,7 @@ def mock_snakemake(rulename, **wildcards):
if os.path.exists(p): if os.path.exists(p):
snakefile = p snakefile = p
break break
workflow = sm.Workflow(snakefile, overwrite_configfiles=[]) workflow = sm.Workflow(snakefile, overwrite_configfiles=[], rerun_triggers=[])
workflow.include(snakefile) workflow.include(snakefile)
workflow.global_resources = {} workflow.global_resources = {}
rule = workflow.get_rule(rulename) rule = workflow.get_rule(rulename)

View File

@ -47,9 +47,10 @@ from _helpers import configure_logging
import pypsa import pypsa
import os import os
import pandas as pd import pandas as pd
import numpy as np
import geopandas as gpd import geopandas as gpd
from shapely.geometry import Polygon
from vresutils.graph import voronoi_partition_pts from scipy.spatial import Voronoi
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -61,6 +62,53 @@ def save_to_geojson(s, fn):
s.to_file(fn, driver='GeoJSON', schema=schema) s.to_file(fn, driver='GeoJSON', schema=schema)
def voronoi_partition_pts(points, outline):
"""
Compute the polygons of a voronoi partition of `points` within the
polygon `outline`. Taken from
https://github.com/FRESNA/vresutils/blob/master/vresutils/graph.py
Attributes
----------
points : Nx2 - ndarray[dtype=float]
outline : Polygon
Returns
-------
polygons : N - ndarray[dtype=Polygon|MultiPolygon]
"""
points = np.asarray(points)
if len(points) == 1:
polygons = [outline]
else:
xmin, ymin = np.amin(points, axis=0)
xmax, ymax = np.amax(points, axis=0)
xspan = xmax - xmin
yspan = ymax - ymin
# to avoid any network positions outside all Voronoi cells, append
# the corners of a rectangle framing these points
vor = Voronoi(np.vstack((points,
[[xmin-3.*xspan, ymin-3.*yspan],
[xmin-3.*xspan, ymax+3.*yspan],
[xmax+3.*xspan, ymin-3.*yspan],
[xmax+3.*xspan, ymax+3.*yspan]])))
polygons = []
for i in range(len(points)):
poly = Polygon(vor.vertices[vor.regions[vor.point_region[i]]])
if not poly.is_valid:
poly = poly.buffer(0)
poly = poly.intersection(outline)
polygons.append(poly)
return np.array(polygons, dtype=object)
if __name__ == "__main__": if __name__ == "__main__":
if 'snakemake' not in globals(): if 'snakemake' not in globals():
from _helpers import mock_snakemake from _helpers import mock_snakemake

View File

@ -40,7 +40,7 @@ Description
""" """
import logging import logging
from _helpers import configure_logging, retrieve_snakemake_keys from _helpers import configure_logging
import atlite import atlite
import geopandas as gpd import geopandas as gpd
@ -73,20 +73,17 @@ if __name__ == "__main__":
snakemake = mock_snakemake('build_natura_raster') snakemake = mock_snakemake('build_natura_raster')
configure_logging(snakemake) configure_logging(snakemake)
paths, config, wildcards, logs, out = retrieve_snakemake_keys(snakemake) cutouts = snakemake.input.cutouts
cutouts = paths.cutouts
xs, Xs, ys, Ys = zip(*(determine_cutout_xXyY(cutout) for cutout in cutouts)) xs, Xs, ys, Ys = zip(*(determine_cutout_xXyY(cutout) for cutout in cutouts))
bounds = transform_bounds(4326, 3035, min(xs), min(ys), max(Xs), max(Ys)) bounds = transform_bounds(4326, 3035, min(xs), min(ys), max(Xs), max(Ys))
transform, out_shape = get_transform_and_shape(bounds, res=100) transform, out_shape = get_transform_and_shape(bounds, res=100)
# adjusted boundaries # adjusted boundaries
shapes = gpd.read_file(paths.natura).to_crs(3035) shapes = gpd.read_file(snakemake.input.natura).to_crs(3035)
raster = ~geometry_mask(shapes.geometry, out_shape[::-1], transform) raster = ~geometry_mask(shapes.geometry, out_shape[::-1], transform)
raster = raster.astype(rio.uint8) raster = raster.astype(rio.uint8)
with rio.open(out[0], 'w', driver='GTiff', dtype=rio.uint8, with rio.open(snakemake.output[0], 'w', driver='GTiff', dtype=rio.uint8,
count=1, transform=transform, crs=3035, compress='lzw', count=1, transform=transform, crs=3035, compress='lzw',
width=raster.shape[1], height=raster.shape[0]) as dst: width=raster.shape[1], height=raster.shape[0]) as dst:
dst.write(raster, indexes=1) dst.write(raster, indexes=1)

View File

@ -203,7 +203,7 @@ if __name__ == '__main__':
pgb.streams.wrap_stderr() pgb.streams.wrap_stderr()
nprocesses = int(snakemake.threads) nprocesses = int(snakemake.threads)
noprogress = not snakemake.config['atlite'].get('show_progress', True) noprogress = not snakemake.config['atlite'].get('show_progress', False)
config = snakemake.config['renewable'][snakemake.wildcards.technology] config = snakemake.config['renewable'][snakemake.wildcards.technology]
resource = config['resource'] # pv panel config / wind turbine config resource = config['resource'] # pv panel config / wind turbine config
correction_factor = config.get('correction_factor', 1.) correction_factor = config.get('correction_factor', 1.)
@ -240,7 +240,7 @@ if __name__ == '__main__':
# use named function np.greater with partially frozen argument instead # use named function np.greater with partially frozen argument instead
# and exclude areas where: -max_depth > grid cell depth # and exclude areas where: -max_depth > grid cell depth
func = functools.partial(np.greater,-config['max_depth']) func = functools.partial(np.greater,-config['max_depth'])
excluder.add_raster(snakemake.input.gebco, codes=func, crs=4236, nodata=-1000) excluder.add_raster(snakemake.input.gebco, codes=func, crs=4326, nodata=-1000)
if 'min_shore_distance' in config: if 'min_shore_distance' in config:
buffer = config['min_shore_distance'] buffer = config['min_shore_distance']

View File

@ -19,7 +19,7 @@ Description
""" """
import logging import logging
from _helpers import configure_logging, retrieve_snakemake_keys from _helpers import configure_logging
import pypsa import pypsa
import pandas as pd import pandas as pd
@ -53,13 +53,11 @@ if __name__ == "__main__":
clusts= '5,full', country= 'all') clusts= '5,full', country= 'all')
configure_logging(snakemake) configure_logging(snakemake)
paths, config, wildcards, logs, out = retrieve_snakemake_keys(snakemake)
plot_kwds = dict(drawstyle="steps-post") plot_kwds = dict(drawstyle="steps-post")
clusters = wildcards.clusts.split(',') clusters = snakemake.wildcards.clusts.split(',')
techs = wildcards.techs.split(',') techs = snakemake.wildcards.techs.split(',')
country = wildcards.country country = snakemake.wildcards.country
if country == 'all': if country == 'all':
country = None country = None
else: else:
@ -68,7 +66,7 @@ if __name__ == "__main__":
fig, axes = plt.subplots(1, len(techs)) fig, axes = plt.subplots(1, len(techs))
for j, cluster in enumerate(clusters): for j, cluster in enumerate(clusters):
net = pypsa.Network(paths[j]) net = pypsa.Network(snakemake.input[j])
for i, tech in enumerate(techs): for i, tech in enumerate(techs):
cum_p_nom_max(net, tech, country).plot(x="p_max_pu", y="cum_p_nom_max", cum_p_nom_max(net, tech, country).plot(x="p_max_pu", y="cum_p_nom_max",
@ -81,4 +79,4 @@ if __name__ == "__main__":
plt.legend(title="Cluster level") plt.legend(title="Cluster level")
fig.savefig(out[0], transparent=True, bbox_inches='tight') fig.savefig(snakemake.output[0], transparent=True, bbox_inches='tight')

View File

@ -21,7 +21,7 @@ Description
import os import os
import logging import logging
from _helpers import configure_logging, retrieve_snakemake_keys from _helpers import configure_logging
import pandas as pd import pandas as pd
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
@ -170,12 +170,12 @@ if __name__ == "__main__":
attr='', ext='png', country='all') attr='', ext='png', country='all')
configure_logging(snakemake) configure_logging(snakemake)
paths, config, wildcards, logs, out = retrieve_snakemake_keys(snakemake) config = snakemake.config
summary = wildcards.summary summary = snakemake.wildcards.summary
try: try:
func = globals()[f"plot_{summary}"] func = globals()[f"plot_{summary}"]
except KeyError: except KeyError:
raise RuntimeError(f"plotting function for {summary} has not been defined") raise RuntimeError(f"plotting function for {summary} has not been defined")
func(os.path.join(paths[0], f"{summary}.csv"), config, out[0]) func(os.path.join(snakemake.input[0], f"{summary}.csv"), config, snakemake.output[0])

View File

@ -37,7 +37,7 @@ Description
""" """
import logging import logging
from _helpers import configure_logging, retrieve_snakemake_keys from _helpers import configure_logging
import pandas as pd import pandas as pd
@ -63,8 +63,6 @@ if __name__ == "__main__":
snakemake = mock_snakemake('prepare_links_p_nom', simpl='', network='elec') snakemake = mock_snakemake('prepare_links_p_nom', simpl='', network='elec')
configure_logging(snakemake) configure_logging(snakemake)
paths, config, wildcards, logs, out = retrieve_snakemake_keys(snakemake)
links_p_nom = pd.read_html('https://en.wikipedia.org/wiki/List_of_HVDC_projects', header=0, match="SwePol")[0] links_p_nom = pd.read_html('https://en.wikipedia.org/wiki/List_of_HVDC_projects', header=0, match="SwePol")[0]
mw = "Power (MW)" mw = "Power (MW)"
@ -76,4 +74,4 @@ if __name__ == "__main__":
links_p_nom['x1'], links_p_nom['y1'] = extract_coordinates(links_p_nom['Converterstation 1']) links_p_nom['x1'], links_p_nom['y1'] = extract_coordinates(links_p_nom['Converterstation 1'])
links_p_nom['x2'], links_p_nom['y2'] = extract_coordinates(links_p_nom['Converterstation 2']) links_p_nom['x2'], links_p_nom['y2'] = extract_coordinates(links_p_nom['Converterstation 2'])
links_p_nom.dropna(subset=['x1', 'y1', 'x2', 'y2']).to_csv(out[0], index=False) links_p_nom.dropna(subset=['x1', 'y1', 'x2', 'y2']).to_csv(snakemake.output[0], index=False)