From 8aff213e9bb67fde4af264de65254035058f1793 Mon Sep 17 00:00:00 2001 From: alonsoju95 Date: Thu, 8 Dec 2022 16:11:32 +0100 Subject: [PATCH 01/58] changes to plot v_nom --- etrago/tools/plot.py | 221 +++++++++++++++++++++++++++++++------------ 1 file changed, 162 insertions(+), 59 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index be3cf6cb6..5c6ccafd0 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -80,7 +80,6 @@ def set_epsg_network(network): set_epsg_network.counter = set_epsg_network.counter + 1 - def plot_osm(x, y, zoom, alpha=0.4): """ Plots openstreetmap as background of network-plots @@ -108,7 +107,9 @@ def plot_osm(x, y, zoom, alpha=0.4): fig, ax = plt.subplots() plt.axis("off") - plotter = tilemapbase.Plotter(extent, tilemapbase.tiles.build_OSM(), zoom=zoom) + plotter = tilemapbase.Plotter( + extent, tilemapbase.tiles.build_OSM(), zoom=zoom + ) plotter.plot(ax, alpha=alpha) # ax.plot(x, y, "ro-") return fig, ax @@ -217,7 +218,9 @@ def plot_line_loading_diff(networkA, networkB, timestep=0, osm=False): set_epsg_network(networkB) plot_osm(osm["x"], osm["y"], osm["zoom"]) # new colormap to make sure 0% difference has the same color in every plot - def shiftedColorMap(cmap, start=0, midpoint=0.5, stop=1.0, name="shiftedcmap"): + def shiftedColorMap( + cmap, start=0, midpoint=0.5, stop=1.0, name="shiftedcmap" + ): """ Function to offset the "center" of a colormap. Useful for data with a negative min and positive max and you want the @@ -279,7 +282,9 @@ def shiftedColorMap(cmap, start=0, midpoint=0.5, stop=1.0, name="shiftedcmap"): ) loading_noswitches.columns = ["noswitch"] diff_network = loading_switches.join(loading_noswitches) - diff_network["noswitch"] = diff_network["noswitch"].fillna(diff_network["switch"]) + diff_network["noswitch"] = diff_network["noswitch"].fillna( + diff_network["switch"] + ) diff_network[networkA.snapshots[timestep]] = ( diff_network["switch"] - diff_network["noswitch"] ) @@ -293,10 +298,13 @@ def shiftedColorMap(cmap, start=0, midpoint=0.5, stop=1.0, name="shiftedcmap"): # plot network with difference in loading and shifted colormap loading = ( - diff_network.loc[:, networkA.snapshots[timestep]] / (networkA.lines.s_nom) + diff_network.loc[:, networkA.snapshots[timestep]] + / (networkA.lines.s_nom) ) * 100 midpoint = 1 - max(loading) / (max(loading) + abs(min(loading))) - shifted_cmap = shiftedColorMap(plt.cm.jet, midpoint=midpoint, name="shifted") + shifted_cmap = shiftedColorMap( + plt.cm.jet, midpoint=midpoint, name="shifted" + ) ll = networkA.plot( line_colors=loading, line_cmap=shifted_cmap, @@ -311,7 +319,9 @@ def shiftedColorMap(cmap, start=0, midpoint=0.5, stop=1.0, name="shiftedcmap"): cb.set_label("Difference in line loading in % of s_nom") -def network_expansion_diff(networkA, networkB, filename=None, boundaries=[], osm=False): +def network_expansion_diff( + networkA, networkB, filename=None, boundaries=[], osm=False +): """Plot relative network expansion derivation of AC- and DC-lines. Parameters @@ -341,11 +351,13 @@ def network_expansion_diff(networkA, networkB, filename=None, boundaries=[], osm cmap = plt.cm.jet extension_lines = 100 * ( - (networkA.lines.s_nom_opt - networkB.lines.s_nom_opt) / networkA.lines.s_nom_opt + (networkA.lines.s_nom_opt - networkB.lines.s_nom_opt) + / networkA.lines.s_nom_opt ) extension_links = 100 * ( - (networkA.links.p_nom_opt - networkB.links.p_nom_opt) / networkA.links.p_nom_opt + (networkA.links.p_nom_opt - networkB.links.p_nom_opt) + / networkA.links.p_nom_opt ) ll = networkA.plot( @@ -378,7 +390,9 @@ def network_expansion_diff(networkA, networkB, filename=None, boundaries=[], osm cb_Link.remove() - cb = plt.colorbar(ll[1], boundaries=v, ticks=v[0:101:10], fraction=0.046, pad=0.04) + cb = plt.colorbar( + ll[1], boundaries=v, ticks=v[0:101:10], fraction=0.046, pad=0.04 + ) cb.set_clim(vmin=boundaries[0], vmax=boundaries[1]) cb.set_label("line extension derivation in %") @@ -408,17 +422,29 @@ def plot_residual_load(network): ] * network.generators_t.p_max_pu[renewables.index].mul( network.snapshot_weightings, axis=0 ) - load = network.loads_t.p_set.mul(network.snapshot_weightings, axis=0).sum(axis=1) + load = network.loads_t.p_set.mul(network.snapshot_weightings, axis=0).sum( + axis=1 + ) all_renew = renewables_t.sum(axis=1) residual_load = load - all_renew plot = residual_load.plot( - title="Residual load", drawstyle="steps", lw=2, color="red", legend=False + title="Residual load", + drawstyle="steps", + lw=2, + color="red", + legend=False, ) plot.set_ylabel("MW") # sorted curve - sorted_residual_load = residual_load.sort_values(ascending=False).reset_index() + sorted_residual_load = residual_load.sort_values( + ascending=False + ).reset_index() plot1 = sorted_residual_load.plot( - title="Sorted residual load", drawstyle="steps", lw=2, color="red", legend=False + title="Sorted residual load", + drawstyle="steps", + lw=2, + color="red", + legend=False, ) plot1.set_ylabel("MW") @@ -454,10 +480,16 @@ def plot_stacked_gen(network, bus=None, resolution="GW", filename=None): pd.concat( [ network.generators_t.p[ - network.generators[network.generators.control != "Slack"].index + network.generators[ + network.generators.control != "Slack" + ].index ], - network.generators_t.p.mul(network.snapshot_weightings, axis=0)[ - network.generators[network.generators.control == "Slack"].index + network.generators_t.p.mul( + network.snapshot_weightings, axis=0 + )[ + network.generators[ + network.generators.control == "Slack" + ].index ] .iloc[:, 0] .apply(lambda x: x if x > 0 else 0), @@ -496,8 +528,12 @@ def plot_stacked_gen(network, bus=None, resolution="GW", filename=None): colors = [colors[col] for col in p_by_carrier.columns] if len(colors) == 1: colors = colors[0] - (p_by_carrier / reso_int).plot(kind="area", ax=ax, linewidth=0, color=colors) - (load / reso_int).plot(ax=ax, legend="load", lw=2, color="darkgrey", style="--") + (p_by_carrier / reso_int).plot( + kind="area", ax=ax, linewidth=0, color=colors + ) + (load / reso_int).plot( + ax=ax, legend="load", lw=2, color="darkgrey", style="--" + ) ax.legend(ncol=4, loc="upper left") ax.set_ylabel(resolution) @@ -543,11 +579,19 @@ def gen_by_c(network): gen = ( pd.concat( [ - network.generators_t.p.mul(etwork.snapshot_weightings, axis=0)[ - network.generators[network.generators.control != "Slack"].index + network.generators_t.p.mul( + etwork.snapshot_weightings, axis=0 + )[ + network.generators[ + network.generators.control != "Slack" + ].index ], - network.generators_t.p.mul(network.snapshot_weightings, axis=0)[ - network.generators[network.generators.control == "Slack"].index + network.generators_t.p.mul( + network.snapshot_weightings, axis=0 + )[ + network.generators[ + network.generators.control == "Slack" + ].index ] .iloc[:, 0] .apply(lambda x: x if x > 0 else 0), @@ -623,7 +667,9 @@ def plot_voltage(network, boundaries=[], osm=False): cb.set_clim(vmin=boundaries[0], vmax=boundaries[1]) cb.set_label("Voltage Magnitude per unit of v_nom") - network.plot(ax=ax, line_widths=pd.Series(0.5, network.lines.index), bus_sizes=0) + network.plot( + ax=ax, line_widths=pd.Series(0.5, network.lines.index), bus_sizes=0 + ) plt.show() @@ -650,7 +696,9 @@ def curtailment(network, carrier="solar", filename=None): network.generators.carrier, axis=1 ).sum() capacity = network.generators.groupby("carrier").sum().at[carrier, "p_nom"] - p_available = network.generators_t.p_max_pu.multiply(network.generators["p_nom"]) + p_available = network.generators_t.p_max_pu.multiply( + network.generators["p_nom"] + ) p_available_by_carrier = p_available.groupby( network.generators.carrier, axis=1 ).sum() @@ -672,7 +720,9 @@ def curtailment(network, carrier="solar", filename=None): p_df[[carrier + " dispatched", carrier + " curtailed"]].plot( kind="area", ax=ax, linewidth=3 ) - p_df[[carrier + " available", carrier + " capacity"]].plot(ax=ax, linewidth=3) + p_df[[carrier + " available", carrier + " capacity"]].plot( + ax=ax, linewidth=3 + ) ax.set_xlabel("") ax.set_ylabel("Power [MW]") @@ -708,15 +758,21 @@ def calc_dispatch_per_carrier(network, timesteps): ] dist = pd.Series( - index=pd.MultiIndex.from_tuples(index, names=["bus", "carrier"]), dtype=float + index=pd.MultiIndex.from_tuples(index, names=["bus", "carrier"]), + dtype=float, ) for i in dist.index: gens = network.generators[ - (network.generators.bus == i[0]) & (network.generators.carrier == i[1]) + (network.generators.bus == i[0]) + & (network.generators.carrier == i[1]) ].index dist[i] = ( - (network.generators_t.p[gens].transpose()[network.snapshots[timesteps]]) + ( + network.generators_t.p[gens].transpose()[ + network.snapshots[timesteps] + ] + ) .sum() .sum() ) @@ -739,11 +795,15 @@ def calc_storage_expansion_per_bus(network): """ - batteries = network.storage_units[network.storage_units.carrier == "battery"] + batteries = network.storage_units[ + network.storage_units.carrier == "battery" + ] h2_overground = network.stores[network.stores.carrier == "H2_overground"] h2_underground = network.stores[network.stores.carrier == "H2_underground"] rural_heat = network.stores[network.stores.carrier == "rural_heat_store"] - central_heat = network.stores[network.stores.carrier == "central_heat_store"] + central_heat = network.stores[ + network.stores.carrier == "central_heat_store" + ] # hydrogen = network.storage_units[network.storage_units.carrier == # 'extendable_hydrogen_storage'] battery_distribution = ( @@ -791,7 +851,8 @@ def calc_storage_expansion_per_bus(network): # index.extend([(idx, 'hydrogen_storage') for idx in network.buses.index]) dist = pd.Series( - index=pd.MultiIndex.from_tuples(index, names=["bus", "carrier"]), dtype=float + index=pd.MultiIndex.from_tuples(index, names=["bus", "carrier"]), + dtype=float, ) dist.iloc[ @@ -989,13 +1050,19 @@ def nodal_gen_dispatch( dispatch_network = ( network.generators_t.p[gens.index] .mul(network.snapshot_weightings.generators, axis=0) - .groupby([network.generators.bus, network.generators.carrier], axis=1) + .groupby( + [network.generators.bus, network.generators.carrier], + axis=1, + ) .sum() ) dispatch_networkB = ( networkB.generators_t.p[gens.index] .mul(networkB.snapshot_weightings.generators, axis=0) - .groupby([networkB.generators.bus, networkB.generators.carrier], axis=1) + .groupby( + [networkB.generators.bus, networkB.generators.carrier], + axis=1, + ) .sum() ) dispatch = dispatch_network - dispatch_networkB @@ -1025,7 +1092,9 @@ def nodal_gen_dispatch( dispatch = dispatch.abs() + 1e-9 else: dispatch = dispatch.sum(level=0) - colors = {s[0]: "green" if s[1] > 0 else "red" for s in dispatch.iteritems()} + colors = { + s[0]: "green" if s[1] > 0 else "red" for s in dispatch.iteritems() + } dispatch = dispatch.abs() subcolors = {"negative": "red", "positive": "green"} import cartopy.crs as ccrs @@ -1096,7 +1165,10 @@ def nodal_production_balance(network, timesteps, scaling=0.00001): residual_load = (gen - load).sum() bus_colors = pd.Series( - {s[0]: "green" if s[1] > 0 else "red" for s in residual_load.iteritems()} + { + s[0]: "green" if s[1] > 0 else "red" + for s in residual_load.iteritems() + } ) bus_sizes = residual_load.abs() * scaling @@ -1130,10 +1202,12 @@ def storage_p_soc(network, mean="1H", filename=None): ] cap_batt = ( - network.storage_units.max_hours[sbatt] * network.storage_units.p_nom_opt[sbatt] + network.storage_units.max_hours[sbatt] + * network.storage_units.p_nom_opt[sbatt] ).sum() cap_hydr = ( - network.storage_units.max_hours[shydr] * network.storage_units.p_nom_opt[shydr] + network.storage_units.max_hours[shydr] + * network.storage_units.p_nom_opt[shydr] ).sum() fig, ax = plt.subplots(1, 1) @@ -1228,7 +1302,6 @@ def storage_p_soc(network, mean="1H", filename=None): ax2.legend(loc=1) ax.set_title("Storage dispatch and state of charge") - if filename is None: plt.show() else: @@ -1262,10 +1335,12 @@ def storage_soc_sorted(network, filename=None): ] cap_batt = ( - network.storage_units.max_hours[sbatt] * network.storage_units.p_nom_opt[sbatt] + network.storage_units.max_hours[sbatt] + * network.storage_units.p_nom_opt[sbatt] ).sum() cap_hydr = ( - network.storage_units.max_hours[shydr] * network.storage_units.p_nom_opt[shydr] + network.storage_units.max_hours[shydr] + * network.storage_units.p_nom_opt[shydr] ).sum() fig, ax = plt.subplots(1, 1) @@ -1424,19 +1499,25 @@ def calc_dc_loading(network, timesteps): network.links.linked_to = network.links.linked_to.astype(str) # Set p_nom_max and line_loading for one directional links - link_load = network.links_t.p0[network.links.index[network.links.linked_to == "0"]] + link_load = network.links_t.p0[ + network.links.index[network.links.linked_to == "0"] + ] p_nom_opt_max = network.links.p_nom_opt[network.links.linked_to == "0"] # Set p_nom_max and line_loading for bidirectional links for i, row in network.links[network.links.linked_to != "0"].iterrows(): - load = pd.DataFrame(index=network.links_t.p0.index, columns=["to", "from"]) + load = pd.DataFrame( + index=network.links_t.p0.index, columns=["to", "from"] + ) load["to"] = network.links_t.p0[row["linked_to"]] load["from"] = network.links_t.p0[i] link_load[i] = load.abs().max(axis=1) p_nom_opt_max[i] = max( row.p_nom_opt, - network.links.p_nom_opt[network.links.index == row["linked_to"]].values[0], + network.links.p_nom_opt[ + network.links.index == row["linked_to"] + ].values[0], ) return ( @@ -1500,21 +1581,24 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): network.lines = network.lines[ network.lines.s_nom_extendable & ( - (network.lines.s_nom_opt - network.lines.s_nom_min) / network.lines.s_nom + (network.lines.s_nom_opt - network.lines.s_nom_min) + / network.lines.s_nom >= ext_min ) ] network.links = network.links[ network.links.p_nom_extendable & ( - (network.links.p_nom_opt - network.links.p_nom_min) / network.links.p_nom + (network.links.p_nom_opt - network.links.p_nom_min) + / network.links.p_nom >= ext_min ) ] for i, row in network.links.iterrows(): linked = network.links[ - (row["bus1"] == network.links.bus0) & (row["bus0"] == network.links.bus1) + (row["bus1"] == network.links.bus0) + & (row["bus0"] == network.links.bus1) ] if not linked.empty: if row["p_nom_opt"] < linked.p_nom_opt.values[0]: @@ -1557,21 +1641,25 @@ def plot_background_grid(network, ax): """ + linkcarrier = pd.Series( + data=network.links.carrier, index=network.links.index + ) + + linkcarrier[linkcarrier != "DC"] = 0 + linkcarrier[linkcarrier == "DC"] = 0.3 + network.plot( ax=ax, line_colors="grey", link_colors="grey", bus_sizes=0, line_widths=0.5, - link_widths=0.3, # 0.55, + link_widths=linkcarrier, # 0.3, geomap=True, projection=ccrs.PlateCarree(), color_geomap=True, ) - network.plot(ax=ax, line_colors='grey', link_colors='grey', - bus_sizes=0, line_widths=0.5, link_widths=0.3,#0.55, - geomap=True, projection=ccrs.PlateCarree(), color_geomap=True) def plot_carrier(etrago, carrier_links, carrier_buses=[], osm=False): @@ -1721,7 +1809,9 @@ def plot_grid( + " to " + str(network.snapshots[timesteps[-1]]) ) - rep_snapshots = network.snapshot_weightings[network.snapshots[timesteps]].sum() + rep_snapshots = network.snapshot_weightings[ + network.snapshots[timesteps] + ].sum() line_colors = calc_ac_loading(network, timesteps).abs() / rep_snapshots link_colors = calc_dc_loading(network, timesteps).abs() / rep_snapshots label = "line loading in p.u." @@ -1740,8 +1830,10 @@ def plot_grid( elif line_colors == "v_nom": title = "Voltage levels" label = "v_nom in kV" + breakpoint() line_colors = network.lines.v_nom - link_colors = network.links.v_nom + link_colors = pd.Series(data=0, index=network.links.index) + plot_background_grid(network, ax) elif line_colors == "expansion_abs": title = "Network expansion" label = "network expansion in MW" @@ -1765,7 +1857,9 @@ def plot_grid( elif line_colors == "q_flow_max": title = "Maximmal reactive power flows" label = "flow in Mvar" - line_colors = abs(network.lines_t.q0.abs().max() / (network.lines.s_nom)) + line_colors = abs( + network.lines_t.q0.abs().max() / (network.lines.s_nom) + ) link_colors = pd.Series(data=0, index=network.links.index) else: logger.warning("line_color {} undefined".format(line_colors)) @@ -1863,7 +1957,9 @@ def plot_grid( handles = [positive, negative] else: for i in network.carriers.color.index: - patch = mpatches.Patch(color=network.carriers.color[i], label=i) + patch = mpatches.Patch( + color=network.carriers.color[i], label=i + ) handles.append(patch) l3 = plt.legend( @@ -1882,7 +1978,9 @@ def plot_grid( v = np.linspace(boundaries[0], boundaries[1], 101) # colorbar for line heatmap - cb = plt.colorbar(ll[1], boundaries=v, ticks=v[0:101:10], fraction=0.046, pad=0.04) + cb = plt.colorbar( + ll[1], boundaries=v, ticks=v[0:101:10], fraction=0.046, pad=0.04 + ) # Set legend label cb.set_label(label) @@ -1999,7 +2097,9 @@ def plot_clusters( ] ] map_buses = map_buses[map_buses["carrier"] == carrier] - map_buses["geom"] = map_buses.apply(lambda x: Point(x["x"], x["y"]), axis=1) + map_buses["geom"] = map_buses.apply( + lambda x: Point(x["x"], x["y"]), axis=1 + ) map_buses["cluster"] = map_buses.index.map(self.busmap["busmap"]) map_buses["cluster_geom"] = map_buses["cluster"].map(new_geom.geom) map_buses["line"] = map_buses.apply( @@ -2027,9 +2127,12 @@ def plot_clusters( .any() ): lines["geom"] = gpd.GeoSeries.from_wkt(lines["geom"]) - lines = gpd.GeoDataFrame(self.busmap["orig_network"].lines, geometry="geom") + lines = gpd.GeoDataFrame( + self.busmap["orig_network"].lines, geometry="geom" + ) lines = lines[ - lines["bus0"].isin(map_buses.index) & lines["bus1"].isin(map_buses.index) + lines["bus0"].isin(map_buses.index) + & lines["bus1"].isin(map_buses.index) ] lines["geom"] = lines.apply( lambda x: x["geom"] From 520bd62dc0797734c2991ed557d1f05ee6ec76b6 Mon Sep 17 00:00:00 2001 From: alonsoju95 Date: Thu, 8 Dec 2022 16:38:36 +0100 Subject: [PATCH 02/58] changes to plot v_nom --- etrago/tools/plot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 5c6ccafd0..5a56c5892 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1640,14 +1640,14 @@ def plot_background_grid(network, ax): None. """ - + breakpoint() linkcarrier = pd.Series( data=network.links.carrier, index=network.links.index ) linkcarrier[linkcarrier != "DC"] = 0 linkcarrier[linkcarrier == "DC"] = 0.3 - + linkcarrier = linkcarrier.astype(float) network.plot( ax=ax, line_colors="grey", From 92c83eed25a072da9a535504704be4287f60a8a0 Mon Sep 17 00:00:00 2001 From: alonsoju95 Date: Fri, 9 Dec 2022 11:30:10 +0100 Subject: [PATCH 03/58] changes to plot v_nom --- etrago/tools/plot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 5a56c5892..ebbc65d9a 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1640,7 +1640,7 @@ def plot_background_grid(network, ax): None. """ - breakpoint() + # breakpoint() linkcarrier = pd.Series( data=network.links.carrier, index=network.links.index ) @@ -1830,7 +1830,7 @@ def plot_grid( elif line_colors == "v_nom": title = "Voltage levels" label = "v_nom in kV" - breakpoint() + # breakpoint() line_colors = network.lines.v_nom link_colors = pd.Series(data=0, index=network.links.index) plot_background_grid(network, ax) From 520b36eaae8d50bdc878ae14f8884503e762e288 Mon Sep 17 00:00:00 2001 From: alonsoju95 Date: Fri, 6 Jan 2023 13:52:44 +0100 Subject: [PATCH 04/58] changes to calc_network_expansion to plot only DC links --- etrago/tools/plot.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index ebbc65d9a..e1500feee 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1577,6 +1577,7 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): DC-line expansion """ + # ´breakpoint() all_network = network.copy() network.lines = network.lines[ network.lines.s_nom_extendable @@ -1603,7 +1604,7 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): if not linked.empty: if row["p_nom_opt"] < linked.p_nom_opt.values[0]: network.links.p_nom_opt[i] = linked.p_nom_opt.values[0] - + breakpoint() if method == "rel": extension_lines = ( @@ -1612,15 +1613,41 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): / network.lines.s_nom ) + # extension_links = ( + # 100 + # * (network.links.p_nom_opt - network.links.p_nom_min) + # / (network.links.p_nom) + # ) + + extension_links = pd.DataFrame( + data=network.links, index=network.links.index + ) + extension_links[extension_links.carrier != "DC"] = 0 extension_links = ( 100 * (network.links.p_nom_opt - network.links.p_nom_min) / (network.links.p_nom) ) + extension_links = extension_links.fillna(0) + # if method == "abs": + # extension_lines = network.lines.s_nom_opt - network.lines.s_nom_min + + # extension_links = network.links.p_nom_opt - network.links.p_nom_min + + # return all_network, extension_lines, extension_links + if method == "abs": extension_lines = network.lines.s_nom_opt - network.lines.s_nom_min + extension_links = pd.DataFrame( + data=network.links, index=network.links.index + ) + extension_links[extension_links.carrier != "DC"] = 0 extension_links = network.links.p_nom_opt - network.links.p_nom_min + # extension_links = ( + # network.links[(network.links.carrier == "DC")].p_nom_opt + # - network.links[(network.links.carrier == "DC")].p_nom_min + # ).set_index(network.links.index) return all_network, extension_lines, extension_links @@ -1830,11 +1857,11 @@ def plot_grid( elif line_colors == "v_nom": title = "Voltage levels" label = "v_nom in kV" - # breakpoint() line_colors = network.lines.v_nom link_colors = pd.Series(data=0, index=network.links.index) plot_background_grid(network, ax) elif line_colors == "expansion_abs": + breakpoint() title = "Network expansion" label = "network expansion in MW" all_network, line_colors, link_colors = calc_network_expansion( @@ -1845,6 +1872,7 @@ def plot_grid( line_widths = 0.5 + (line_colors / ext_width) link_widths = 0.5 + (link_colors / ext_width) elif line_colors == "expansion_rel": + breakpoint() title = "Network expansion" label = "network expansion in %" all_network, line_colors, link_colors = calc_network_expansion( From b85bd435abcae70e6406fd547b54d56ca3f28fd7 Mon Sep 17 00:00:00 2001 From: alonsoju95 Date: Fri, 6 Jan 2023 14:20:10 +0100 Subject: [PATCH 05/58] empty spaces erased --- etrago/tools/plot.py | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index e1500feee..1a6ec7623 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1577,7 +1577,7 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): DC-line expansion """ - # ´breakpoint() + all_network = network.copy() network.lines = network.lines[ network.lines.s_nom_extendable @@ -1604,7 +1604,7 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): if not linked.empty: if row["p_nom_opt"] < linked.p_nom_opt.values[0]: network.links.p_nom_opt[i] = linked.p_nom_opt.values[0] - breakpoint() + if method == "rel": extension_lines = ( @@ -1613,12 +1613,6 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): / network.lines.s_nom ) - # extension_links = ( - # 100 - # * (network.links.p_nom_opt - network.links.p_nom_min) - # / (network.links.p_nom) - # ) - extension_links = pd.DataFrame( data=network.links, index=network.links.index ) @@ -1629,12 +1623,6 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): / (network.links.p_nom) ) extension_links = extension_links.fillna(0) - # if method == "abs": - # extension_lines = network.lines.s_nom_opt - network.lines.s_nom_min - - # extension_links = network.links.p_nom_opt - network.links.p_nom_min - - # return all_network, extension_lines, extension_links if method == "abs": extension_lines = network.lines.s_nom_opt - network.lines.s_nom_min @@ -1644,10 +1632,6 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): ) extension_links[extension_links.carrier != "DC"] = 0 extension_links = network.links.p_nom_opt - network.links.p_nom_min - # extension_links = ( - # network.links[(network.links.carrier == "DC")].p_nom_opt - # - network.links[(network.links.carrier == "DC")].p_nom_min - # ).set_index(network.links.index) return all_network, extension_lines, extension_links @@ -1667,7 +1651,7 @@ def plot_background_grid(network, ax): None. """ - # breakpoint() + linkcarrier = pd.Series( data=network.links.carrier, index=network.links.index ) @@ -1861,7 +1845,6 @@ def plot_grid( link_colors = pd.Series(data=0, index=network.links.index) plot_background_grid(network, ax) elif line_colors == "expansion_abs": - breakpoint() title = "Network expansion" label = "network expansion in MW" all_network, line_colors, link_colors = calc_network_expansion( @@ -1872,7 +1855,6 @@ def plot_grid( line_widths = 0.5 + (line_colors / ext_width) link_widths = 0.5 + (link_colors / ext_width) elif line_colors == "expansion_rel": - breakpoint() title = "Network expansion" label = "network expansion in %" all_network, line_colors, link_colors = calc_network_expansion( From a7a17ab87fc6a82409e59d98d11e23b1fe1a94d9 Mon Sep 17 00:00:00 2001 From: alonsoju95 Date: Fri, 20 Jan 2023 15:17:18 +0100 Subject: [PATCH 06/58] expansion abs only plots AC buses --- etrago/tools/plot.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 1a6ec7623..663df1455 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -580,7 +580,7 @@ def gen_by_c(network): pd.concat( [ network.generators_t.p.mul( - etwork.snapshot_weightings, axis=0 + network.snapshot_weightings, axis=0 )[ network.generators[ network.generators.control != "Slack" @@ -1651,7 +1651,7 @@ def plot_background_grid(network, ax): None. """ - + breakpoint() linkcarrier = pd.Series( data=network.links.carrier, index=network.links.index ) @@ -1792,7 +1792,7 @@ def plot_grid( network = self.disaggregated_network.copy() else: network = self.network.copy() - + breakpoint() # Set colors for plotting plotting_colors(network) @@ -1875,7 +1875,7 @@ def plot_grid( logger.warning("line_color {} undefined".format(line_colors)) # Set bus colors - + breakpoint() if bus_colors == "nodal_production_balance": bus_scaling = bus_sizes bus_sizes, bus_colors = nodal_production_balance( @@ -1916,8 +1916,18 @@ def plot_grid( bus_legend = "PowerToH2" bus_unit = "TW" - else: - logger.warning("bus_color {} undefined".format(bus_colors)) + # else: + # logger.warning("bus_color {} undefined".format(bus_colors)) + elif bus_colors == "grey": + bus_scaling = bus_sizes + bus_unit = "" + bus_legend = "" + bus_sizes = pd.Series( + data=network.buses.carrier, index=network.buses.index + ) + bus_sizes[bus_sizes != "AC"] = 0 + bus_sizes[bus_sizes == "AC"] = 1 * bus_scaling + bus_scaling = bus_sizes ll = network.plot( line_colors=line_colors, @@ -1936,7 +1946,8 @@ def plot_grid( ) # legends for bus sizes and colors - if type(bus_sizes) != float: + if bus_colors != "grey": + # if type(bus_sizes) != float: handles = make_legend_circles_for( [bus_sizes.min(), bus_sizes.max()], scale=1, facecolor="gray" ) From 452045ba93f3233f15a7fe47d2d49fcc6063638f Mon Sep 17 00:00:00 2001 From: alonsoju95 Date: Wed, 25 Jan 2023 19:12:10 +0100 Subject: [PATCH 07/58] check v_nom --- etrago/tools/plot.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 663df1455..b96cc51ef 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1651,7 +1651,7 @@ def plot_background_grid(network, ax): None. """ - breakpoint() + # breakpoint() linkcarrier = pd.Series( data=network.links.carrier, index=network.links.index ) @@ -1792,7 +1792,7 @@ def plot_grid( network = self.disaggregated_network.copy() else: network = self.network.copy() - breakpoint() + # breakpoint() # Set colors for plotting plotting_colors(network) @@ -1875,7 +1875,7 @@ def plot_grid( logger.warning("line_color {} undefined".format(line_colors)) # Set bus colors - breakpoint() + # breakpoint() if bus_colors == "nodal_production_balance": bus_scaling = bus_sizes bus_sizes, bus_colors = nodal_production_balance( @@ -1920,8 +1920,8 @@ def plot_grid( # logger.warning("bus_color {} undefined".format(bus_colors)) elif bus_colors == "grey": bus_scaling = bus_sizes - bus_unit = "" - bus_legend = "" + # bus_unit = "" + # bus_legend = "" bus_sizes = pd.Series( data=network.buses.carrier, index=network.buses.index ) @@ -2002,6 +2002,7 @@ def plot_grid( cb = plt.colorbar( ll[1], boundaries=v, ticks=v[0:101:10], fraction=0.046, pad=0.04 ) + # Set legend label cb.set_label(label) From 9e107aa6c0d86d181bbc2eed8255732afbcf19dc Mon Sep 17 00:00:00 2001 From: alonsoju95 Date: Mon, 13 Feb 2023 23:59:23 +0100 Subject: [PATCH 08/58] update --- etrago/tools/plot.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index b96cc51ef..b8f0b6538 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1811,7 +1811,7 @@ def plot_grid( fig, ax = plt.subplots( subplot_kw={"projection": ccrs.PlateCarree()}, figsize=(5, 5) ) - + # breakpoint() # Set line colors if line_colors == "line_loading": title = ( @@ -1901,6 +1901,7 @@ def plot_grid( bus_sizes = bus_scaling * calc_dispatch_per_carrier(network, timesteps) bus_legend = "Dispatch" bus_unit = "TW" + elif ( bus_colors == "PowerToH2" ): # PowerToH2 plots p_nom_opt of links with carrier=power to H2 From 15596aef3401a6c1ae7749967a969e7f9a5e5e77 Mon Sep 17 00:00:00 2001 From: alonsoju95 Date: Tue, 14 Feb 2023 12:36:48 +0100 Subject: [PATCH 09/58] update --- etrago/tools/plot.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index b8f0b6538..a8e0a9bfc 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1651,24 +1651,21 @@ def plot_background_grid(network, ax): None. """ - # breakpoint() - linkcarrier = pd.Series( - data=network.links.carrier, index=network.links.index - ) - linkcarrier[linkcarrier != "DC"] = 0 - linkcarrier[linkcarrier == "DC"] = 0.3 - linkcarrier = linkcarrier.astype(float) + link_widths = pd.Series(index=network.links.index, data=0) + link_widths.loc[network.links.carrier == "DC"] = 0.3 + network.plot( ax=ax, line_colors="grey", link_colors="grey", bus_sizes=0, line_widths=0.5, - link_widths=linkcarrier, # 0.3, + link_widths=link_widths, # 0.3, geomap=True, projection=ccrs.PlateCarree(), color_geomap=True, + # boundaries=[1.5, 16, 46.8, 58], ) @@ -1792,7 +1789,7 @@ def plot_grid( network = self.disaggregated_network.copy() else: network = self.network.copy() - # breakpoint() + # Set colors for plotting plotting_colors(network) @@ -1811,7 +1808,7 @@ def plot_grid( fig, ax = plt.subplots( subplot_kw={"projection": ccrs.PlateCarree()}, figsize=(5, 5) ) - # breakpoint() + # Set line colors if line_colors == "line_loading": title = ( @@ -1875,7 +1872,7 @@ def plot_grid( logger.warning("line_color {} undefined".format(line_colors)) # Set bus colors - # breakpoint() + if bus_colors == "nodal_production_balance": bus_scaling = bus_sizes bus_sizes, bus_colors = nodal_production_balance( From 30176e924009b3468688afcf9202c0d13a6e4565 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 21 Mar 2023 09:02:30 +0100 Subject: [PATCH 10/58] fix line_loading plot in plot_grid --- etrago/tools/plot.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 8de936881..e66c60a18 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1440,7 +1440,7 @@ def calc_ac_loading(network, timesteps): Returns ------- pandas.Series - ACC line loading in MVA + AC line loading in MVA """ loading_lines = ( @@ -2318,11 +2318,11 @@ def plot_grid( ].sum() line_colors = calc_ac_loading(network, timesteps).abs() / rep_snapshots link_colors = calc_dc_loading(network, timesteps).abs() / rep_snapshots - link_widths = 2 + pd.Series(1, index=link_colors.index) - link_widths[link_colors.index.isin(network.links[network.links.carrier!="DC"].index)] = 0 + link_widths = network.links.carrier + link_widths = link_widths.apply(lambda x: 2 if x == "DC" else 0) label = "line loading in p.u." #Only active flow direction is displayed! - flow = pd.Series(index=network.branches().index, dtype="float64") + flow = pd.Series(1, index=network.branches().index, dtype="float64") flow.iloc[flow.index.get_level_values("component") == "Line"] = ( mul_weighting(network, network.lines_t.p0) .loc[network.snapshots[timesteps]] @@ -2333,11 +2333,13 @@ def plot_grid( flow.iloc[flow.index.get_level_values("component") == "Link"] = ( calc_dc_loading(network, timesteps) / rep_snapshots ).values + flow = flow[(flow.index.get_level_values("component")=="Line")| - (flow.index.isin(link_widths[link_colors.index.isin( + (flow.index.isin(link_widths[link_widths.index.isin( network.links[network.links.carrier=="DC"].index) ].index, level=1))] - flow = flow.apply(lambda x: x+5 if x > 0 else x-5) + flow[flow<0] = -1 + flow[flow>0] = 1 elif line_colors == "v_nom": title = "Voltage levels" @@ -2461,7 +2463,7 @@ def plot_grid( title=title, geomap=False, ) - + # legends for bus sizes and colors if bus_colors != "grey": # if type(bus_sizes) != float: From 712cb1f96acbb9c5cc4d6410929cd6bf03812fa4 Mon Sep 17 00:00:00 2001 From: ClaraBuettner Date: Thu, 22 Dec 2022 13:45:10 +0100 Subject: [PATCH 11/58] Fix mul_weighting function --- etrago/tools/plot.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index e66c60a18..e0628fc96 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1423,7 +1423,8 @@ def mul_weighting(network, timeseries): timeseries considering snapshot_weightings """ - return timeseries.mul(network.snapshot_weightings["objective"], axis=0) + return timeseries.mul(network.snapshot_weightings.generators, axis=0) + def calc_ac_loading(network, timesteps): From ff3d9029c9cc49e1e73fea6eaa99355df4e4535e Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 21 Mar 2023 09:53:47 +0100 Subject: [PATCH 12/58] change boundaries for plots --- etrago/tools/plot.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index e0628fc96..acc94a8ed 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1671,6 +1671,7 @@ def plot_background_grid(network, ax): geomap=True, projection=ccrs.PlateCarree(), color_geomap=True, + boundaries = [1.5,16,46.8,58], ) else: network.plot( @@ -2433,7 +2434,7 @@ def plot_grid( bus_sizes[bus_sizes != "AC"] = 0 bus_sizes[bus_sizes == "AC"] = 1 * bus_scaling bus_scaling = bus_sizes - + if cartopy_present: ll = network.plot( line_colors=line_colors, @@ -2449,6 +2450,7 @@ def plot_grid( geomap=False, projection=ccrs.PlateCarree(), color_geomap=True, + boundaries = [1.5,16,46.8,58], ) else: ll = network.plot( @@ -2463,6 +2465,7 @@ def plot_grid( flow=flow, title=title, geomap=False, + boundaries = [1.5,16,46.8,58], ) # legends for bus sizes and colors From c87a1fbebe245a4808f1f2c2b511f362b7c4b678 Mon Sep 17 00:00:00 2001 From: ClaraBuettner Date: Thu, 22 Dec 2022 13:48:04 +0100 Subject: [PATCH 13/58] Add option to set legend entries --- etrago/tools/plot.py | 69 ++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index acc94a8ed..7e4b364c8 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2202,22 +2202,19 @@ def plot_carrier(network, carrier_links=["AC"], carrier_buses=["AC"]): ax.autoscale() -def plot_grid( - self, - line_colors, - bus_sizes=0.001, - bus_colors="grey", - timesteps=range(2), - osm=False, - boundaries=None, - filename=None, - disaggregated=False, - ext_min=0.1, - ext_width=False, -): - """Function that plots etrago.network and results for lines and buses - - +def plot_grid(self, + line_colors, + bus_sizes=0.001, + bus_colors='grey', + timesteps=range(2), + osm=False, + boundaries=None, + filename=None, + disaggregated=False, + ext_min=0.1, + ext_width=False, + legend_entries = 'all'): + """ Function that plots etrago.network and results for lines and buses Parameters ---------- @@ -2499,6 +2496,10 @@ def plot_grid( positive = mpatches.Patch(color="green", label="generation") negative = mpatches.Patch(color="red", label="consumption") handles = [positive, negative] + elif legend_entries != 'all': + for i in legend_entries: + patch = mpatches.Patch(color=network.carriers.color[i], label=i) + handles.append(patch) else: for i in network.carriers.color.index: patch = mpatches.Patch( @@ -2507,27 +2508,27 @@ def plot_grid( handles.append(patch) l3 = plt.legend( - handles=handles, loc="upper left", ncol=3, bbox_to_anchor=(-0.1, 0) + handles=handles, loc="upper left", + ncol=2, bbox_to_anchor=(0, 0) ) ax.add_artist(l3) - # Set fixed boundaries if selected in parameters - if not boundaries: - boundaries = [ - min(line_colors.min(), link_colors.min()), - max(line_colors.max(), link_colors.max()), - ] - - # Create ticks for legend - v = np.linspace(boundaries[0], boundaries[1], 101) - - # colorbar for line heatmap - cb = plt.colorbar( - ll[1], boundaries=v, ticks=v[0:101:10], fraction=0.046, pad=0.04 - ) - - # Set legend label - cb.set_label(label) + if type(line_colors) != str: + print(111111) + # Set fixed boundaries if selected in parameters + if not boundaries: + boundaries = [ + min(line_colors.min(), link_colors.min()), + max(line_colors.max(), link_colors.max()), + ] + + # Create ticks for legend + v = np.linspace(boundaries[0], boundaries[1], 101) + + # colorbar for line heatmap + cb = plt.colorbar(ll[2], boundaries=v, ticks=v[0:101:10], fraction=0.046, pad=0.04) + # Set legend label + cb.set_label(label) # Show plot or save to file if filename is None: From c1fee2ef7f75fac943340b1233275814e1b8950b Mon Sep 17 00:00:00 2001 From: ClaraBuettner Date: Thu, 22 Dec 2022 13:48:48 +0100 Subject: [PATCH 14/58] Add plot to show dynamic line rating usage --- etrago/tools/plot.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 7e4b364c8..b56556ff7 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2373,6 +2373,28 @@ def plot_grid(self, network.lines_t.q0.abs().max() / (network.lines.s_nom) ) link_colors = pd.Series(data=0, index=network.links.index) + elif line_colors == "dlr": + title = "Dynamic line rating" + label = "MWh above nominal capacity" + plot_background_grid(network, ax) + line_loading = network.lines_t.p0.mul(1/network.lines.s_nom_opt) + dlr_usage = line_loading[line_loading.abs() > 1].fillna(0).mul( + network.snapshot_weightings.generators, axis = 0).abs().sum() + line_colors = dlr_usage + if ext_width != False: + line_widths = 0.5 + (line_colors / ext_width) + link_colors = pd.Series(data=0, index=network.links.index) + + elif line_colors == 'blue': + title = "" + label = "" + line_colors = 'blue' + link_colors = 'blue' + plot_background_grid(network, ax) + link_widths = 0 + line_widths = 0 + + else: logger.warning("line_color {} undefined".format(line_colors)) From edd0cf9c80cfdc54f1c878c67a35116001c72342 Mon Sep 17 00:00:00 2001 From: ClaraBuettner Date: Thu, 22 Dec 2022 13:49:18 +0100 Subject: [PATCH 15/58] Add plot for flexibility usage per node --- etrago/tools/plot.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index b56556ff7..6eb901b4a 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2425,7 +2425,23 @@ def plot_grid(self, bus_sizes = bus_scaling * calc_dispatch_per_carrier(network, timesteps) bus_legend = "Dispatch" bus_unit = "TW" - + elif bus_colors == 'flexibility_usage': + #import pdb; pdb.set_trace() + bus_scaling = bus_sizes + flex_links = network.links[network.links.carrier.isin([ + 'dsm', 'BEV charger', + #'central_heat_store_charger', + #'central_heat_store_discharger', + #'rural_heat_store_charger', + #'rural_heat_store_discharger' + ])] + flex_links["p0_sum"] = network.links_t.p0[flex_links.index].mul( + network.snapshot_weightings.generators, axis=0).abs().sum() + flex_links["p1_sum"] = network.links_t.p1[flex_links.index].mul( + network.snapshot_weightings.generators, axis=0).sum() + bus_sizes = bus_scaling * flex_links.groupby(['bus0', 'carrier']).p0_sum.sum() + bus_unit = "TWh" + bus_legend = "flexibility_usage" elif ( bus_colors == "PowerToH2" ): # PowerToH2 plots p_nom_opt of links with carrier=power to H2 From 4798efd19c7773cd2cf173e9ab1f04b4dba63a9b Mon Sep 17 00:00:00 2001 From: ClaraBuettner Date: Thu, 22 Dec 2022 13:49:37 +0100 Subject: [PATCH 16/58] Add h2 storage plot --- etrago/tools/plot.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 6eb901b4a..433a3c014 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2442,6 +2442,14 @@ def plot_grid(self, bus_sizes = bus_scaling * flex_links.groupby(['bus0', 'carrier']).p0_sum.sum() bus_unit = "TWh" bus_legend = "flexibility_usage" + elif bus_colors == "h2_storage_expansion": + bus_scaling = bus_sizes + bus_sizes = bus_scaling * calc_storage_expansion_per_bus(network) + bus_sizes = bus_sizes.reset_index() + bus_sizes = bus_sizes[bus_sizes.carrier.str.contains('H2')] + bus_sizes.set_index(['bus','carrier'],inplace=True) + bus_legend = "Storage expansion" + bus_unit = "GW" elif ( bus_colors == "PowerToH2" ): # PowerToH2 plots p_nom_opt of links with carrier=power to H2 @@ -2456,9 +2464,6 @@ def plot_grid(self, bus_colors = coloring()["power_to_H2"] bus_legend = "PowerToH2" bus_unit = "TW" - - # else: - # logger.warning("bus_color {} undefined".format(bus_colors)) elif bus_colors == "grey": bus_scaling = bus_sizes # bus_unit = "" @@ -2469,6 +2474,8 @@ def plot_grid(self, bus_sizes[bus_sizes != "AC"] = 0 bus_sizes[bus_sizes == "AC"] = 1 * bus_scaling bus_scaling = bus_sizes + else: + logger.warning("bus_color {} undefined".format(bus_colors)) if cartopy_present: ll = network.plot( @@ -2503,6 +2510,7 @@ def plot_grid(self, boundaries = [1.5,16,46.8,58], ) + # legends for bus sizes and colors if bus_colors != "grey": # if type(bus_sizes) != float: From 0cdad076096e54a93bd296f5338c4c1524103a66 Mon Sep 17 00:00:00 2001 From: ClaraBuettner Date: Tue, 14 Feb 2023 08:53:01 +0100 Subject: [PATCH 17/58] Add color for 'heat' --- etrago/tools/plot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 433a3c014..297f25fe7 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -153,6 +153,7 @@ def coloring(): "H2_grid": "green", "H2_saltcavern": "darkgreen", "central_heat_store": "firebrick", + "heat": "firebrick", "rural_heat_store": "salmon", "AC": "blue", "nuclear": "palegreen", From 49290e56c010cdf4e8078d4d05472521cd501856 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 21 Mar 2023 10:14:54 +0100 Subject: [PATCH 18/58] Change boundaries of map --- etrago/tools/plot.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 297f25fe7..3b1fe2daf 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1672,7 +1672,7 @@ def plot_background_grid(network, ax): geomap=True, projection=ccrs.PlateCarree(), color_geomap=True, - boundaries = [1.5,16,46.8,58], + boundaries=[-2.5, 16, 46.8, 58], ) else: network.plot( @@ -2493,7 +2493,7 @@ def plot_grid(self, geomap=False, projection=ccrs.PlateCarree(), color_geomap=True, - boundaries = [1.5,16,46.8,58], + boundaries=[-2.5, 16, 46.8, 58] ) else: ll = network.plot( @@ -2508,7 +2508,7 @@ def plot_grid(self, flow=flow, title=title, geomap=False, - boundaries = [1.5,16,46.8,58], + boundaries=[-2.5, 16, 46.8, 58] ) From fc5a3aea11d9e457fd6555614e0e2da14fdb96af Mon Sep 17 00:00:00 2001 From: ClaraBuettner Date: Tue, 14 Feb 2023 08:54:05 +0100 Subject: [PATCH 19/58] Add different legend sizes for stores --- etrago/tools/plot.py | 130 +++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 55 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 3b1fe2daf..bc3817616 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2203,19 +2203,26 @@ def plot_carrier(network, carrier_links=["AC"], carrier_buses=["AC"]): ax.autoscale() -def plot_grid(self, - line_colors, - bus_sizes=0.001, - bus_colors='grey', - timesteps=range(2), - osm=False, - boundaries=None, - filename=None, - disaggregated=False, - ext_min=0.1, - ext_width=False, - legend_entries = 'all'): - """ Function that plots etrago.network and results for lines and buses +def plot_grid( + self, + line_colors, + bus_sizes=0.001, + bus_colors="grey", + timesteps=range(2), + osm=False, + boundaries=None, + filename=None, + disaggregated=False, + ext_min=0.1, + ext_width=False, + legend_entries="all", + scaling_store_expansion = { + "H2": 50, + "heat": 0.1, + "battery": 10, + } +): + """Function that plots etrago.network and results for lines and buses Parameters ---------- @@ -2411,6 +2418,13 @@ def plot_grid(self, elif bus_colors == "storage_expansion": bus_scaling = bus_sizes bus_sizes = bus_scaling * calc_storage_expansion_per_bus(network) + for store_carrier in ["H2", "heat", "battery"]: + bus_sizes[bus_sizes.index.get_level_values('carrier').str.contains(store_carrier)] *= scaling_store_expansion[store_carrier] + bus_legend = "Storage expansion" + bus_unit = "GW" + elif bus_colors == "h2_battery_storage_expansion": + bus_scaling = bus_sizes + bus_sizes = bus_scaling * calc_storage_expansion_per_bus(network, carriers=["battery", "H2_overground", "H2_underground"]) bus_legend = "Storage expansion" bus_unit = "GW" elif bus_colors == "storage_distribution": @@ -2480,8 +2494,8 @@ def plot_grid(self, if cartopy_present: ll = network.plot( - line_colors=line_colors, - link_colors=link_colors, + line_colors=line_colors.mul(1e-3), + link_colors=link_colors.mul(1e-3), line_cmap=plt.cm.jet, link_cmap=plt.cm.jet, bus_sizes=bus_sizes, @@ -2489,16 +2503,16 @@ def plot_grid(self, line_widths=line_widths, link_widths=link_widths, flow=flow, - title=title, + #title=title, geomap=False, projection=ccrs.PlateCarree(), color_geomap=True, - boundaries=[-2.5, 16, 46.8, 58] + boundaries=[-2.5, 16, 46.8, 58], ) else: - ll = network.plot( - line_colors=line_colors, - link_colors=link_colors, + ll =network.plot( + line_colors=line_colors.mul(1e-3), + link_colors=link_colors.mul(1e-3), line_cmap=plt.cm.jet, link_cmap=plt.cm.jet, bus_sizes=bus_sizes, @@ -2506,25 +2520,29 @@ def plot_grid(self, line_widths=line_widths, link_widths=link_widths, flow=flow, - title=title, + #title=title, geomap=False, - boundaries=[-2.5, 16, 46.8, 58] + boundaries=[-2.5, 16, 46.8, 58], ) # legends for bus sizes and colors - if bus_colors != "grey": - # if type(bus_sizes) != float: - handles = make_legend_circles_for( - [bus_sizes.min(), bus_sizes.max()], scale=1, facecolor="gray" - ) - labels = [ - ("{} " + bus_unit).format(s) - for s in ( - round(bus_sizes.min() / bus_scaling / 1000, 0), - round(bus_sizes.max() / bus_scaling / 1000, 0), - ) - ] + if type(bus_sizes) != float: + handles = [] + labels = [] + for i in legend_entries: + try: + max_value = bus_sizes[bus_sizes.index.get_level_values('carrier').str.contains(i)].max() + except: + max_value = bus_sizes.max() + handles.append(make_legend_circles_for( + [max_value], scale=1, facecolor=network.carriers.color[i], + )[0]) + + if scaling_store_expansion: + labels.append(f"{round(max_value / bus_scaling / scaling_store_expansion[i]/1000, 2)} GWh " + i) + else: + labels.append(f"{round(max_value / bus_scaling /1000, 2)} GWh " + i) l2 = ax.legend( handles, @@ -2535,33 +2553,35 @@ def plot_grid(self, framealpha=1.0, title=bus_legend, handler_map=make_handler_map_to_scale_circles_as_in(ax), + prop={'size': 8} ) ax.add_artist(l2) - handles = [] - if bus_legend == "Nodal production balance": - positive = mpatches.Patch(color="green", label="generation") - negative = mpatches.Patch(color="red", label="consumption") - handles = [positive, negative] - elif legend_entries != 'all': - for i in legend_entries: - patch = mpatches.Patch(color=network.carriers.color[i], label=i) - handles.append(patch) - else: - for i in network.carriers.color.index: - patch = mpatches.Patch( - color=network.carriers.color[i], label=i - ) - handles.append(patch) + plt.setp(l2.get_title(),fontsize='9') - l3 = plt.legend( - handles=handles, loc="upper left", - ncol=2, bbox_to_anchor=(0, 0) - ) - ax.add_artist(l3) + if not scaling_store_expansion: + + handles = [] + if bus_legend == "Nodal production balance": + positive = mpatches.Patch(color="green", label="generation") + negative = mpatches.Patch(color="red", label="consumption") + handles = [positive, negative] + elif legend_entries != "all": + for i in legend_entries: + patch = mpatches.Patch(color=network.carriers.color[i], label=i) + handles.append(patch) + else: + for i in network.carriers.color.index: + patch = mpatches.Patch(color=network.carriers.color[i], label=i) + handles.append(patch) + + l3 = plt.legend( + handles=handles, loc="upper left", ncol=2, bbox_to_anchor=(0, 0) + ) + ax.add_artist(l3) if type(line_colors) != str: - print(111111) + # Set fixed boundaries if selected in parameters if not boundaries: boundaries = [ From 1ace72e34d84d2a411d825448c311c9e4b9a27de Mon Sep 17 00:00:00 2001 From: ClaraBuettner Date: Tue, 14 Feb 2023 08:54:44 +0100 Subject: [PATCH 20/58] Delete unused lines --- etrago/tools/plot.py | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index bc3817616..0f0538ebc 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2440,21 +2440,28 @@ def plot_grid( bus_sizes = bus_scaling * calc_dispatch_per_carrier(network, timesteps) bus_legend = "Dispatch" bus_unit = "TW" - elif bus_colors == 'flexibility_usage': - #import pdb; pdb.set_trace() + elif bus_colors == "flexibility_usage": bus_scaling = bus_sizes - flex_links = network.links[network.links.carrier.isin([ - 'dsm', 'BEV charger', - #'central_heat_store_charger', - #'central_heat_store_discharger', - #'rural_heat_store_charger', - #'rural_heat_store_discharger' - ])] - flex_links["p0_sum"] = network.links_t.p0[flex_links.index].mul( - network.snapshot_weightings.generators, axis=0).abs().sum() - flex_links["p1_sum"] = network.links_t.p1[flex_links.index].mul( - network.snapshot_weightings.generators, axis=0).sum() - bus_sizes = bus_scaling * flex_links.groupby(['bus0', 'carrier']).p0_sum.sum() + flex_links = network.links[ + network.links.carrier.isin( + [ + "dsm", + "BEV charger", + ] + ) + ] + flex_links["p0_sum"] = ( + network.links_t.p0[flex_links.index] + .mul(network.snapshot_weightings.generators, axis=0) + .abs() + .sum() + ) + flex_links["p1_sum"] = ( + network.links_t.p1[flex_links.index] + .mul(network.snapshot_weightings.generators, axis=0) + .sum() + ) + bus_sizes = bus_scaling * flex_links.groupby(["bus0", "carrier"]).p0_sum.sum() bus_unit = "TWh" bus_legend = "flexibility_usage" elif bus_colors == "h2_storage_expansion": From a4f665c48a8e483fc53c5095313f65d6a4c9e0d4 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 21 Mar 2023 10:48:52 +0100 Subject: [PATCH 21/58] Scale line exapsnion to GVA --- etrago/tools/plot.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 0f0538ebc..1b22e6f8b 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2499,10 +2499,13 @@ def plot_grid( else: logger.warning("bus_color {} undefined".format(bus_colors)) + if type(link_colors) != str: + link_colors=link_colors.mul(1e-3) + line_colors=line_colors.mul(1e-3) if cartopy_present: ll = network.plot( - line_colors=line_colors.mul(1e-3), - link_colors=link_colors.mul(1e-3), + line_colors=line_colors, + link_colors=link_colors, line_cmap=plt.cm.jet, link_cmap=plt.cm.jet, bus_sizes=bus_sizes, @@ -2518,8 +2521,8 @@ def plot_grid( ) else: ll =network.plot( - line_colors=line_colors.mul(1e-3), - link_colors=link_colors.mul(1e-3), + line_colors=line_colors, + link_colors=link_colors, line_cmap=plt.cm.jet, link_cmap=plt.cm.jet, bus_sizes=bus_sizes, From abbf70f93c60e222d69394d888cfbb26670e439b Mon Sep 17 00:00:00 2001 From: ClaraBuettner Date: Tue, 14 Feb 2023 08:55:29 +0100 Subject: [PATCH 22/58] Fix colorbar for all line collections --- etrago/tools/plot.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 1b22e6f8b..126fc6466 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2601,9 +2601,13 @@ def plot_grid( # Create ticks for legend v = np.linspace(boundaries[0], boundaries[1], 101) - + for l_collection in ll: + l_collection.set_clim(boundaries[0], boundaries[1]) + # colorbar for line heatmap - cb = plt.colorbar(ll[2], boundaries=v, ticks=v[0:101:10], fraction=0.046, pad=0.04) + cb = plt.colorbar( + ll[1], values=v, ticks=v[0:101:10], fraction=0.028, pad=0.04, + ) # Set legend label cb.set_label(label) From dbcc32d8dfa30bfeb75f3613ef93e0dba3f1b56f Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 21 Mar 2023 16:07:53 +0100 Subject: [PATCH 23/58] fix line_loading plot in plot_grid --- etrago/tools/plot.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 126fc6466..57d3fcdb9 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2326,8 +2326,10 @@ def plot_grid( line_colors = calc_ac_loading(network, timesteps).abs() / rep_snapshots link_colors = calc_dc_loading(network, timesteps).abs() / rep_snapshots link_widths = network.links.carrier - link_widths = link_widths.apply(lambda x: 2 if x == "DC" else 0) + link_widths = link_widths.apply(lambda x: 10 if x == "DC" else 0) + line_widths = 10 label = "line loading in p.u." + plot_background_grid(network, ax) #Only active flow direction is displayed! flow = pd.Series(1, index=network.branches().index, dtype="float64") flow.iloc[flow.index.get_level_values("component") == "Line"] = ( @@ -2364,6 +2366,8 @@ def plot_grid( if ext_width != False: line_widths = 0.5 + (line_colors / ext_width) link_widths = 0.5 + (link_colors / ext_width) + else: + link_widths = 2.0 elif line_colors == "expansion_rel": title = "Network expansion" label = "network expansion in %" @@ -2499,7 +2503,7 @@ def plot_grid( else: logger.warning("bus_color {} undefined".format(bus_colors)) - if type(link_colors) != str: + if not isinstance(link_colors, (pd.Series, float)): link_colors=link_colors.mul(1e-3) line_colors=line_colors.mul(1e-3) if cartopy_present: @@ -2537,7 +2541,7 @@ def plot_grid( # legends for bus sizes and colors - if type(bus_sizes) != float: + if not isinstance(bus_sizes, (pd.Series, float)): handles = [] labels = [] for i in legend_entries: @@ -2613,7 +2617,7 @@ def plot_grid( # Show plot or save to file if filename is None: - if type(bus_sizes) != float: + if not isinstance(bus_sizes, (pd.Series, float)): logger.warning("Legend of bus sizes will change when zooming") plt.show() else: From b95d32d1023cc25a4d66c31f8806cac767e50a93 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Wed, 22 Mar 2023 12:00:07 +0100 Subject: [PATCH 24/58] fix plot nodal_production_balance --- etrago/tools/plot.py | 121 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 117 insertions(+), 4 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 57d3fcdb9..c8114524d 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1153,7 +1153,114 @@ def nodal_production_balance(network, timesteps, scaling=0.00001): 'green' for producer and 'red' for consumer """ + def import_gen_from_links(network): + from pypsa.networkclustering import aggregategenerators + from etrago.cluster.spatial import strategies_generators + """ + create gas generators from links in order to not lose them when + dropping non-electric carriers + """ + # Discard all generators < 1kW + discard_gen = network.links[network.links["p_nom"] <= 0.001].index + network.links.drop(discard_gen, inplace=True) + for df in network.links_t: + if not network.links_t[df].empty: + network.links_t[df].drop( + columns=discard_gen.values, inplace=True, errors="ignore" + ) + + gas_to_add = network.links[ + network.links.carrier.isin( + [ + "central_gas_CHP", + "OCGT", + "H2_to_power", + "industrial_gas_CHP", + ] + ) + ].copy() + + # Drop generators from the links table + network.links.drop(gas_to_add.index, inplace=True) + gas_to_add.rename(columns={"bus1": "bus"}, inplace=True) + + # Create generators' names like in network.generators + gas_to_add["Generator"] = ( + gas_to_add["bus"] + " " + gas_to_add.index + gas_to_add["carrier"] + ) + gas_to_add_orig = gas_to_add.copy() + gas_to_add.set_index("Generator", drop=True, inplace=True) + gas_to_add = gas_to_add[ + gas_to_add.columns[ + gas_to_add.columns.isin(network.generators.columns) + ] + ] + + network.import_components_from_dataframe(gas_to_add, "Generator") + + # Dealing with generators_t + columns_new = network.links_t.p1.columns[ + network.links_t.p1.columns.isin(gas_to_add_orig.index) + ] + + new_gen_t = network.links_t.p1[columns_new] * -1 + new_gen_t.rename(columns=gas_to_add_orig["Generator"], inplace=True) + network.generators_t.p = network.generators_t.p.join(new_gen_t) + + # Drop generators from the links_t table + for df in network.links_t: + if not network.links_t[df].empty: + network.links_t[df].drop( + columns=gas_to_add_orig.index, + inplace=True, + errors="ignore", + ) + + # Group generators per bus if needed + if not ( + network.generators.groupby(["bus", "carrier"]).p_nom.count() == 1 + ).all(): + network.generators["weight"] = network.generators.p_nom + df, df_t = aggregategenerators( + network, + busmap=pd.Series( + index=network.buses.index, data=network.buses.index + ), + custom_strategies=strategies_generators(), + ) + + # Keep control arguments from generators + control = network.generators.groupby( + ["bus", "carrier"] + ).control.first() + control.index = ( + control.index.get_level_values(0) + + " " + + control.index.get_level_values(1) + ) + df.control = control + + # Drop non-aggregated generators + network.mremove("Generator", network.generators.index) + + # Insert aggregated generators and time series + network.import_components_from_dataframe(df, "Generator") + + for attr, data in df_t.items(): + if not data.empty: + network.import_series_from_dataframe( + data, "Generator", attr + ) + + return + + import_gen_from_links(network) + + ac_buses = network.buses[network.buses.carrier == "AC"].index + network.generators = network.generators[network.generators.bus.isin(ac_buses)] + network.generators_t.p = network.generators_t.p.loc[:,network.generators_t.p.columns.isin(network.generators.index)] + gen = ( mul_weighting(network, network.generators_t.p) .groupby(network.generators.bus, axis=1) @@ -1177,7 +1284,9 @@ def nodal_production_balance(network, timesteps, scaling=0.00001): ) bus_sizes = residual_load.abs() * scaling - + bus_sizes = pd.Series(data= bus_sizes, index = network.buses.index).fillna(0) + + bus_colors = pd.Series(data= bus_colors, index = network.buses.index).fillna("grey") return bus_sizes, bus_colors @@ -2379,12 +2488,13 @@ def plot_grid( line_widths = 0.5 + (line_colors / ext_width) link_widths = 0.5 + (link_colors / ext_width) elif line_colors == "q_flow_max": - title = "Maximmal reactive power flows" + title = "Maximum reactive power flows" label = "flow in Mvar" line_colors = abs( network.lines_t.q0.abs().max() / (network.lines.s_nom) ) link_colors = pd.Series(data=0, index=network.links.index) + plot_background_grid(network, ax) elif line_colors == "dlr": title = "Dynamic line rating" label = "MWh above nominal capacity" @@ -2507,6 +2617,9 @@ def plot_grid( link_colors=link_colors.mul(1e-3) line_colors=line_colors.mul(1e-3) if cartopy_present: + #breakpoint() + + ll = network.plot( line_colors=line_colors, link_colors=link_colors, @@ -2517,7 +2630,7 @@ def plot_grid( line_widths=line_widths, link_widths=link_widths, flow=flow, - #title=title, + title=title, geomap=False, projection=ccrs.PlateCarree(), color_geomap=True, @@ -2534,7 +2647,7 @@ def plot_grid( line_widths=line_widths, link_widths=link_widths, flow=flow, - #title=title, + title=title, geomap=False, boundaries=[-2.5, 16, 46.8, 58], ) From f4c0e5240fdc19f8a43093f169e9835cfbfaf104 Mon Sep 17 00:00:00 2001 From: ClaraBuettner Date: Wed, 22 Mar 2023 14:35:08 +0100 Subject: [PATCH 25/58] fix plot legends --- etrago/tools/plot.py | 71 ++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index c8114524d..551395644 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2467,7 +2467,7 @@ def plot_grid( plot_background_grid(network, ax) elif line_colors == "expansion_abs": title = "Network expansion" - label = "network expansion in MW" + label = "network expansion in GVA" all_network, line_colors, link_colors = calc_network_expansion( network, method="abs", ext_min=ext_min ) @@ -2477,6 +2477,8 @@ def plot_grid( link_widths = 0.5 + (link_colors / ext_width) else: link_widths = 2.0 + link_colors = link_colors.mul(1e-3) + line_colors = line_colors.mul(1e-3) elif line_colors == "expansion_rel": title = "Network expansion" label = "network expansion in %" @@ -2499,9 +2501,14 @@ def plot_grid( title = "Dynamic line rating" label = "MWh above nominal capacity" plot_background_grid(network, ax) - line_loading = network.lines_t.p0.mul(1/network.lines.s_nom_opt) - dlr_usage = line_loading[line_loading.abs() > 1].fillna(0).mul( - network.snapshot_weightings.generators, axis = 0).abs().sum() + line_loading = network.lines_t.p0.mul(1 / (network.lines.s_nom_opt*network.lines.s_max_pu)) + dlr_usage = ( + line_loading[line_loading.abs() > 1] + .fillna(0) + .mul(network.snapshot_weightings.generators, axis=0) + .abs() + .sum() + ) line_colors = dlr_usage if ext_width != False: line_widths = 0.5 + (line_colors / ext_width) @@ -2613,13 +2620,7 @@ def plot_grid( else: logger.warning("bus_color {} undefined".format(bus_colors)) - if not isinstance(link_colors, (pd.Series, float)): - link_colors=link_colors.mul(1e-3) - line_colors=line_colors.mul(1e-3) if cartopy_present: - #breakpoint() - - ll = network.plot( line_colors=line_colors, link_colors=link_colors, @@ -2652,24 +2653,44 @@ def plot_grid( boundaries=[-2.5, 16, 46.8, 58], ) - # legends for bus sizes and colors - if not isinstance(bus_sizes, (pd.Series, float)): + if type(bus_sizes) != float: handles = [] labels = [] - for i in legend_entries: - try: - max_value = bus_sizes[bus_sizes.index.get_level_values('carrier').str.contains(i)].max() - except: - max_value = bus_sizes.max() - handles.append(make_legend_circles_for( - [max_value], scale=1, facecolor=network.carriers.color[i], - )[0]) - - if scaling_store_expansion: - labels.append(f"{round(max_value / bus_scaling / scaling_store_expansion[i]/1000, 2)} GWh " + i) - else: - labels.append(f"{round(max_value / bus_scaling /1000, 2)} GWh " + i) + + if scaling_store_expansion: + for i in legend_entries: + try: + max_value = bus_sizes[ + bus_sizes.index.get_level_values("carrier").str.contains(i) + ].max() + except: + max_value = bus_sizes.max() + handles.append( + make_legend_circles_for( + [max_value], + scale=1, + facecolor=network.carriers.color[i], + )[0] + ) + + + labels.append( + f"{round(max_value / bus_scaling / scaling_store_expansion[i]/1000, 0).astype(int)} GWh " + + i + ) + else: + max_value = bus_sizes.max() + labels.append( + f"{round(max_value / bus_scaling /1000, 0)} GWh " + ) + handles.append( + make_legend_circles_for( + [max_value], + scale=1, + facecolor="grey", + )[0] + ) l2 = ax.legend( handles, From f1e1760dd0b1b24af9e5e682b1a69d62d17eb77b Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Thu, 23 Mar 2023 10:46:11 +0100 Subject: [PATCH 26/58] fix storage_expansion plot --- etrago/tools/plot.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 551395644..b6c135f92 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -124,6 +124,7 @@ def coloring(): "power_to_H2": "cyan", "H2_overground": "cyan", "H2_underground": "cyan", + "H2": "cyan", "dsm-cts": "dodgerblue", "dsm-ind-osm": "dodgerblue", "dsm-ind-sites": "dodgerblue", @@ -2528,6 +2529,14 @@ def plot_grid( logger.warning("line_color {} undefined".format(line_colors)) # Set bus colors + if bus_colors in ["nodal_production_balance", "storage_expansion", + "h2_battery_storage_expansion", "storage_distribution", + "gen_dist", "flexibility_usage", "h2_storage_expansion", + "PowerToH2", + ]: + use_legend = True + else: + use_legend = False if bus_colors == "nodal_production_balance": bus_scaling = bus_sizes @@ -2654,11 +2663,12 @@ def plot_grid( ) # legends for bus sizes and colors - if type(bus_sizes) != float: + if use_legend: handles = [] labels = [] - if scaling_store_expansion: + if not isinstance(legend_entries, list): + raise Exception("When using scaling_store_expansion, the argument legend_entries must be a list of carrier of interest") for i in legend_entries: try: max_value = bus_sizes[ @@ -2673,8 +2683,6 @@ def plot_grid( facecolor=network.carriers.color[i], )[0] ) - - labels.append( f"{round(max_value / bus_scaling / scaling_store_expansion[i]/1000, 0).astype(int)} GWh " + i From 3788938aa8e15b40376a9e03377dfe218f4c0b06 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Thu, 23 Mar 2023 11:57:44 +0100 Subject: [PATCH 27/58] change title plot line_loading --- etrago/tools/plot.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index b6c135f92..6f6ca7911 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2424,12 +2424,7 @@ def plot_grid( # Set line colors if line_colors == "line_loading": - title = ( - "Mean loading from " - + str(network.snapshots[timesteps[0]]) - + " to " - + str(network.snapshots[timesteps[-1]]) - ) + title = "Mean line loading" rep_snapshots = network.snapshot_weightings["objective"][ network.snapshots[timesteps] ].sum() From 6fe87839d1ff4c6f11092c1737ae6ef539a561b8 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Thu, 23 Mar 2023 11:58:31 +0100 Subject: [PATCH 28/58] fix units plot q_flow_max --- etrago/tools/plot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 6f6ca7911..592e1fe5b 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2487,7 +2487,7 @@ def plot_grid( link_widths = 0.5 + (link_colors / ext_width) elif line_colors == "q_flow_max": title = "Maximum reactive power flows" - label = "flow in Mvar" + label = "flow in pu" line_colors = abs( network.lines_t.q0.abs().max() / (network.lines.s_nom) ) From 730642353f8b2e26a6a17c8da71e1855e3e49f32 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Thu, 23 Mar 2023 15:47:50 +0100 Subject: [PATCH 29/58] add missing carriers to coloring --- etrago/tools/plot.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 592e1fe5b..9cf8e3f1f 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -133,6 +133,8 @@ def coloring(): "central_resistive_heater": "blueviolet", "rural_heat_pump": "violet", "CH4": "yellow", + "CH4_biogas": "yellow", + "CH4_NG": "yellow", "CH4_to_H2": "yellowgreen", "industrial_gas_CHP": "olive", "rural_gas_boiler": "sandybrown", @@ -181,6 +183,7 @@ def coloring(): "battery": "blue", "pumped_hydro": "indigo", "BEV charger": "indigo", + "others": "dimgrey" } return colors From 114a92005ce368f301d85c400f4374699270289f Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Thu, 23 Mar 2023 15:48:43 +0100 Subject: [PATCH 30/58] fix gen_dist plot --- etrago/tools/plot.py | 111 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 9cf8e3f1f..5dd8f3cc3 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -756,7 +756,114 @@ def calc_dispatch_per_carrier(network, timesteps): dispatch per carrier """ + def import_gen_from_links(network): + from pypsa.networkclustering import aggregategenerators + from etrago.cluster.spatial import strategies_generators + """ + create gas generators from links in order to not lose them when + dropping non-electric carriers + """ + # Discard all generators < 1kW + discard_gen = network.links[network.links["p_nom"] <= 0.001].index + network.links.drop(discard_gen, inplace=True) + for df in network.links_t: + if not network.links_t[df].empty: + network.links_t[df].drop( + columns=discard_gen.values, inplace=True, errors="ignore" + ) + + gas_to_add = network.links[ + network.links.carrier.isin( + [ + "central_gas_CHP", + "OCGT", + "H2_to_power", + "industrial_gas_CHP", + ] + ) + ].copy() + + # Drop generators from the links table + network.links.drop(gas_to_add.index, inplace=True) + + gas_to_add.rename(columns={"bus1": "bus"}, inplace=True) + + # Create generators' names like in network.generators + gas_to_add["Generator"] = ( + gas_to_add["bus"] + " " + gas_to_add.index + gas_to_add["carrier"] + ) + gas_to_add_orig = gas_to_add.copy() + gas_to_add.set_index("Generator", drop=True, inplace=True) + gas_to_add = gas_to_add[ + gas_to_add.columns[ + gas_to_add.columns.isin(network.generators.columns) + ] + ] + + network.import_components_from_dataframe(gas_to_add, "Generator") + + # Dealing with generators_t + columns_new = network.links_t.p1.columns[ + network.links_t.p1.columns.isin(gas_to_add_orig.index) + ] + + new_gen_t = network.links_t.p1[columns_new] * -1 + new_gen_t.rename(columns=gas_to_add_orig["Generator"], inplace=True) + network.generators_t.p = network.generators_t.p.join(new_gen_t) + + # Drop generators from the links_t table + for df in network.links_t: + if not network.links_t[df].empty: + network.links_t[df].drop( + columns=gas_to_add_orig.index, + inplace=True, + errors="ignore", + ) + + # Group generators per bus if needed + if not ( + network.generators.groupby(["bus", "carrier"]).p_nom.count() == 1 + ).all(): + network.generators["weight"] = network.generators.p_nom + df, df_t = aggregategenerators( + network, + busmap=pd.Series( + index=network.buses.index, data=network.buses.index + ), + custom_strategies=strategies_generators(), + ) + # Keep control arguments from generators + control = network.generators.groupby( + ["bus", "carrier"] + ).control.first() + control.index = ( + control.index.get_level_values(0) + + " " + + control.index.get_level_values(1) + ) + df.control = control + + # Drop non-aggregated generators + network.mremove("Generator", network.generators.index) + + # Insert aggregated generators and time series + network.import_components_from_dataframe(df, "Generator") + + for attr, data in df_t.items(): + if not data.empty: + network.import_series_from_dataframe( + data, "Generator", attr + ) + + return + + import_gen_from_links(network) + + ac_buses = network.buses[network.buses.carrier == "AC"].index + network.generators = network.generators[network.generators.bus.isin(ac_buses)] + network.generators_t.p = network.generators_t.p.loc[:,network.generators_t.p.columns.isin(network.generators.index)] + index = [ (network.generators.bus[idx], network.generators.carrier[idx]) for idx in network.generators.index @@ -2424,6 +2531,8 @@ def plot_grid( else: fig, ax = plt.subplots(figsize=(5, 5)) + + fig.set_tight_layout(True) # Set line colors if line_colors == "line_loading": @@ -2626,7 +2735,7 @@ def plot_grid( bus_scaling = bus_sizes else: logger.warning("bus_color {} undefined".format(bus_colors)) - + if cartopy_present: ll = network.plot( line_colors=line_colors, From 222e2e3bebaafc76671260224ca59db678cf2053 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Fri, 24 Mar 2023 09:34:02 +0100 Subject: [PATCH 31/58] dont delete no DC links when calc network expansion --- etrago/tools/plot.py | 62 +++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 5dd8f3cc3..3ed84f1fa 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1794,7 +1794,7 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): Returns ------- - all_network : :class:`pypsa.Network + network_c : :class:`pypsa.Network Whole network including not extended lines extension_lines : pandas.Series AC-line expansion @@ -1803,64 +1803,66 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): """ - all_network = network.copy() + network_c = network.copy() - network.lines = network.lines[ - network.lines.s_nom_extendable + network_c.lines = network_c.lines[ + network_c.lines.s_nom_extendable & ( - (network.lines.s_nom_opt - network.lines.s_nom_min) - / network.lines.s_nom + (network_c.lines.s_nom_opt - network_c.lines.s_nom_min) + / network_c.lines.s_nom >= ext_min ) ] - network.links = network.links[ - network.links.p_nom_extendable - & (network.links.carrier == "DC") + network_c.links = network_c.links[ + network_c.links.p_nom_extendable + & (network_c.links.carrier == "DC") & ( - (network.links.p_nom_opt - network.links.p_nom_min) - / network.links.p_nom + (network_c.links.p_nom_opt - network_c.links.p_nom_min) + / network_c.links.p_nom >= ext_min ) ] - for i, row in network.links.iterrows(): - linked = network.links[ - (row["bus1"] == network.links.bus0) - & (row["bus0"] == network.links.bus1) + for i, row in network_c.links.iterrows(): + linked = network_c.links[ + (row["bus1"] == network_c.links.bus0) + & (row["bus0"] == network_c.links.bus1) ] if not linked.empty: if row["p_nom_opt"] < linked.p_nom_opt.values[0]: - network.links.p_nom_opt[i] = linked.p_nom_opt.values[0] + network_c.links.p_nom_opt[i] = linked.p_nom_opt.values[0] if method == "rel": extension_lines = ( 100 - * (network.lines.s_nom_opt - network.lines.s_nom_min) - / network.lines.s_nom + * (network_c.lines.s_nom_opt - network_c.lines.s_nom_min) + / network_c.lines.s_nom ) extension_links = pd.DataFrame( - data=network.links, index=network.links.index + data=network_c.links, index=network_c.links.index ) extension_links[extension_links.carrier != "DC"] = 0 extension_links = ( 100 - * (network.links.p_nom_opt - network.links.p_nom_min) - / (network.links.p_nom) + * (network_c.links.p_nom_opt - network_c.links.p_nom_min) + / (network_c.links.p_nom) ) extension_links = extension_links.fillna(0) if method == "abs": - extension_lines = network.lines.s_nom_opt - network.lines.s_nom_min + extension_lines = network_c.lines.s_nom_opt - network_c.lines.s_nom_min extension_links = pd.DataFrame( - data=network.links, index=network.links.index + data=network_c.links, index=network_c.links.index ) extension_links[extension_links.carrier != "DC"] = 0 - extension_links = network.links.p_nom_opt - network.links.p_nom_min + extension_links = network_c.links.p_nom_opt - network_c.links.p_nom_min - return all_network, extension_lines, extension_links + extension_lines = pd.Series(data=extension_lines, index= network.lines.index).fillna(0) + extension_links = pd.Series(data=extension_links, index= network.links.index).fillna(0) + return network, extension_lines, extension_links def plot_background_grid(network, ax): @@ -2582,9 +2584,12 @@ def plot_grid( plot_background_grid(all_network, ax) if ext_width != False: line_widths = 0.5 + (line_colors / ext_width) - link_widths = 0.5 + (link_colors / ext_width) + link_widths = 0.5 + (line_colors / ext_width) else: - link_widths = 2.0 + dc_link = network.links.index[network.links.carrier == "DC"] + link_widths = pd.Series(0, index=network.links.index) + link_widths.loc[dc_link] = 2 + link_colors = link_colors.mul(1e-3) line_colors = line_colors.mul(1e-3) elif line_colors == "expansion_rel": @@ -2725,8 +2730,6 @@ def plot_grid( bus_unit = "TW" elif bus_colors == "grey": bus_scaling = bus_sizes - # bus_unit = "" - # bus_legend = "" bus_sizes = pd.Series( data=network.buses.carrier, index=network.buses.index ) @@ -2829,6 +2832,7 @@ def plot_grid( positive = mpatches.Patch(color="green", label="generation") negative = mpatches.Patch(color="red", label="consumption") handles = [positive, negative] + elif legend_entries != "all": for i in legend_entries: patch = mpatches.Patch(color=network.carriers.color[i], label=i) From 0d97fe4ce8e98d2e06da0b79e7777ddb1e2f4aa1 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Fri, 24 Mar 2023 09:52:13 +0100 Subject: [PATCH 32/58] update function calc_storage_expansion_per_bus --- etrago/tools/plot.py | 157 ++++++++++++++++++++++--------------------- 1 file changed, 81 insertions(+), 76 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 3ed84f1fa..6af07299f 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -892,74 +892,30 @@ def import_gen_from_links(network): return dist -def calc_storage_expansion_per_bus(network): +def calc_storage_expansion_per_bus( + network, + carriers=[ + "battery", + "H2_overground", + "H2_underground", + "rural_heat_store", + "central_heat_store", + ], +): """Function that calculates storage expansion per bus and technology - Parameters ---------- network : PyPSA network container Holds topology of grid including results from powerflow analysis - Returns ------- dist : pandas.Series storage expansion per bus and technology - """ - - batteries = network.storage_units[ - network.storage_units.carrier == "battery" - ] - h2_overground = network.stores[network.stores.carrier == "H2_overground"] - h2_underground = network.stores[network.stores.carrier == "H2_underground"] - rural_heat = network.stores[network.stores.carrier == "rural_heat_store"] - central_heat = network.stores[ - network.stores.carrier == "central_heat_store" - ] - # hydrogen = network.storage_units[network.storage_units.carrier == - # 'extendable_hydrogen_storage'] - battery_distribution = ( - network.storage_units.p_nom_opt[batteries.index] - .groupby(network.storage_units.bus) - .sum() - .reindex(network.buses.index, fill_value=0.0) - ) - h2_over_distribution = ( - network.stores.e_nom_opt[h2_overground.index] - .groupby(network.stores.bus) - .sum() - .reindex(network.buses.index, fill_value=0.0) - ) - h2_under_distribution = ( - network.stores.e_nom_opt[h2_underground.index] - .groupby(network.stores.bus) - .sum() - .reindex(network.buses.index, fill_value=0.0) - ) - rural_heat_distribution = ( - network.stores.e_nom_opt[rural_heat.index] - .groupby(network.stores.bus) - .sum() - .reindex(network.buses.index, fill_value=0.0) - ) - central_heat_distribution = ( - network.stores.e_nom_opt[central_heat.index] - .groupby(network.stores.bus) - .sum() - .reindex(network.buses.index, fill_value=0.0) - ) - # hydrogen_distribution =\ - # network.storage_units.p_nom_opt[hydrogen.index].groupby( - # network.storage_units.bus).sum().reindex( - # network.buses.index, fill_value=0.) index = [(idx, "battery") for idx in network.buses.index] - for c in [ - "H2_overground", - "H2_underground", - "rural_heat_store", - "central_heat_store", - ]: - index.extend([(idx, c) for idx in network.buses.index]) + for c in carriers: + if c != "battery": + index.extend([(idx, c) for idx in network.buses.index]) # index.extend([(idx, 'hydrogen_storage') for idx in network.buses.index]) dist = pd.Series( @@ -967,25 +923,74 @@ def calc_storage_expansion_per_bus(network): dtype=float, ) - dist.iloc[ - dist.index.get_level_values("carrier") == "battery" - ] = battery_distribution.sort_index().values - dist.iloc[ - dist.index.get_level_values("carrier") == "H2_overground" - ] = h2_over_distribution.sort_index().values - dist.iloc[ - dist.index.get_level_values("carrier") == "H2_underground" - ] = h2_under_distribution.sort_index().values - dist.iloc[ - dist.index.get_level_values("carrier") == "rural_heat_store" - ] = rural_heat_distribution.sort_index().values - dist.iloc[ - dist.index.get_level_values("carrier") == "central_heat_store" - ] = central_heat_distribution.sort_index().values - # dist.iloc[dist.index.get_level_values('carrier') == 'hydrogen_storage'] = \ - # hydrogen_distribution.sort_index().values - # network.carriers.color['hydrogen_storage'] = 'orange' - # network.carriers.color['battery_storage'] = 'blue' + if "battery" in carriers: + batteries = network.storage_units[ + network.storage_units.carrier == "battery" + ] + battery_distribution = ( + network.storage_units.p_nom_opt[batteries.index] + .groupby(network.storage_units.bus) + .sum() + .reindex(network.buses.index, fill_value=0.0) + ).mul(6) + dist.iloc[ + dist.index.get_level_values("carrier") == "battery" + ] = battery_distribution.sort_index().values + if "H2_overground" in carriers: + h2_overground = network.stores[ + network.stores.carrier == "H2_overground" + ] + h2_over_distribution = ( + network.stores.e_nom_opt[h2_overground.index] + .groupby(network.stores.bus) + .sum() + .reindex(network.buses.index, fill_value=0.0) + ) + dist.iloc[ + dist.index.get_level_values("carrier") == "H2_overground" + ] = h2_over_distribution.sort_index().values + + if "H2_overground" in carriers: + h2_underground = network.stores[ + network.stores.carrier == "H2_underground" + ] + h2_under_distribution = ( + network.stores.e_nom_opt[h2_underground.index] + .groupby(network.stores.bus) + .sum() + .reindex(network.buses.index, fill_value=0.0) + ) + dist.iloc[ + dist.index.get_level_values("carrier") == "H2_underground" + ] = h2_under_distribution.sort_index().values + + if "rural_heat_store" in carriers: + rural_heat = network.stores[ + network.stores.carrier == "rural_heat_store" + ] + rural_heat_distribution = ( + network.stores.e_nom_opt[rural_heat.index] + .groupby(network.stores.bus) + .sum() + .reindex(network.buses.index, fill_value=0.0) + ) + + dist.iloc[ + dist.index.get_level_values("carrier") == "rural_heat_store" + ] = rural_heat_distribution.sort_index().values + if "central_heat_store" in carriers: + central_heat = network.stores[ + network.stores.carrier == "central_heat_store" + ] + central_heat_distribution = ( + network.stores.e_nom_opt[central_heat.index] + .groupby(network.stores.bus) + .sum() + .reindex(network.buses.index, fill_value=0.0) + ) + dist.iloc[ + dist.index.get_level_values("carrier") == "central_heat_store" + ] = central_heat_distribution.sort_index().values return dist From 449abca8edf5893ccd3cd0743b9006842a0143cd Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Fri, 24 Mar 2023 09:53:35 +0100 Subject: [PATCH 33/58] raise exception in storage expansion plot --- etrago/tools/plot.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 6af07299f..81ec4c2b3 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2663,6 +2663,11 @@ def plot_grid( bus_legend = "Nodal production balance" bus_unit = "TWh" elif bus_colors == "storage_expansion": + if not isinstance(scaling_store_expansion, dict): + raise Exception("""To plot storage_expansion, the argument scaling_store_expansion must be a dictionary like: + {"H2": 50, + "heat": 0.1, + "battery": 10}""") bus_scaling = bus_sizes bus_sizes = bus_scaling * calc_storage_expansion_per_bus(network) for store_carrier in ["H2", "heat", "battery"]: From 0d7334ab43f37ffbc97b999e3f9e2860b3f413d3 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Mon, 27 Mar 2023 12:07:22 +0200 Subject: [PATCH 34/58] fix plot h2_battery_storage_expansion --- etrago/tools/plot.py | 66 ++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 81ec4c2b3..7300b97c3 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -933,9 +933,12 @@ def calc_storage_expansion_per_bus( .sum() .reindex(network.buses.index, fill_value=0.0) ).mul(6) - dist.iloc[ + + battery_distribution.index = pd.MultiIndex.from_tuples([(idx, "battery") for idx in battery_distribution.index]) + + dist.loc[ dist.index.get_level_values("carrier") == "battery" - ] = battery_distribution.sort_index().values + ] = battery_distribution if "H2_overground" in carriers: h2_overground = network.stores[ network.stores.carrier == "H2_overground" @@ -946,9 +949,12 @@ def calc_storage_expansion_per_bus( .sum() .reindex(network.buses.index, fill_value=0.0) ) - dist.iloc[ + + h2_over_distribution.index = pd.MultiIndex.from_tuples([(idx, "H2_overground") for idx in h2_over_distribution.index]) + + dist.loc[ dist.index.get_level_values("carrier") == "H2_overground" - ] = h2_over_distribution.sort_index().values + ] = h2_over_distribution if "H2_overground" in carriers: h2_underground = network.stores[ @@ -960,9 +966,12 @@ def calc_storage_expansion_per_bus( .sum() .reindex(network.buses.index, fill_value=0.0) ) - dist.iloc[ + + h2_under_distribution.index = pd.MultiIndex.from_tuples([(idx, "H2_underground") for idx in h2_under_distribution.index]) + + dist.loc[ dist.index.get_level_values("carrier") == "H2_underground" - ] = h2_under_distribution.sort_index().values + ] = h2_under_distribution if "rural_heat_store" in carriers: rural_heat = network.stores[ @@ -974,10 +983,12 @@ def calc_storage_expansion_per_bus( .sum() .reindex(network.buses.index, fill_value=0.0) ) + + rural_heat_distribution.index = pd.MultiIndex.from_tuples([(idx, "rural_heat_store") for idx in rural_heat_distribution.index]) - dist.iloc[ + dist.loc[ dist.index.get_level_values("carrier") == "rural_heat_store" - ] = rural_heat_distribution.sort_index().values + ] = rural_heat_distribution if "central_heat_store" in carriers: central_heat = network.stores[ network.stores.carrier == "central_heat_store" @@ -988,9 +999,12 @@ def calc_storage_expansion_per_bus( .sum() .reindex(network.buses.index, fill_value=0.0) ) - dist.iloc[ + + central_heat_distribution.index = pd.MultiIndex.from_tuples([(idx, "central_heat_store") for idx in central_heat_distribution.index]) + + dist.loc[ dist.index.get_level_values("carrier") == "central_heat_store" - ] = central_heat_distribution.sort_index().values + ] = central_heat_distribution return dist @@ -2646,14 +2660,7 @@ def plot_grid( logger.warning("line_color {} undefined".format(line_colors)) # Set bus colors - if bus_colors in ["nodal_production_balance", "storage_expansion", - "h2_battery_storage_expansion", "storage_distribution", - "gen_dist", "flexibility_usage", "h2_storage_expansion", - "PowerToH2", - ]: - use_legend = True - else: - use_legend = False + bus_legend = False if bus_colors == "nodal_production_balance": bus_scaling = bus_sizes @@ -2677,7 +2684,21 @@ def plot_grid( elif bus_colors == "h2_battery_storage_expansion": bus_scaling = bus_sizes bus_sizes = bus_scaling * calc_storage_expansion_per_bus(network, carriers=["battery", "H2_overground", "H2_underground"]) - bus_legend = "Storage expansion" + if (("battery" not in scaling_store_expansion.keys()) | + ("H2_overground" not in scaling_store_expansion.keys()) | + ("H2_underground" not in scaling_store_expansion.keys())): + raise Exception("""To plot h2_battery_storage_expansion, the argument scaling_store_expansion must be a dictionary like: + {"H2_overground": 1, + "H2_underground": 1, + "battery": 1,}""") + + for store_carrier in ["battery", "H2_overground", "H2_underground"]: + bus_sizes[ + bus_sizes.index.get_level_values("carrier").str.contains( + store_carrier + ) + ] *= scaling_store_expansion[store_carrier] + bus_legend = "Battery and H2 storage expansion" bus_unit = "GW" elif bus_colors == "storage_distribution": bus_scaling = bus_sizes @@ -2783,12 +2804,15 @@ def plot_grid( ) # legends for bus sizes and colors - if use_legend: + if bus_legend: handles = [] labels = [] if scaling_store_expansion: if not isinstance(legend_entries, list): - raise Exception("When using scaling_store_expansion, the argument legend_entries must be a list of carrier of interest") + if bus_legend == "Storage expansion": + legend_entries = list(scaling_store_expansion.keys()) + if bus_legend == "Battery and H2 storage expansion": + legend_entries = ["battery", "H2_overground", "H2_underground"] for i in legend_entries: try: max_value = bus_sizes[ From 31d54768f8e8307036c9710d9680d720787408eb Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Mon, 27 Mar 2023 13:32:04 +0200 Subject: [PATCH 35/58] show just needed lables --- etrago/tools/plot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 7300b97c3..56d5dee1c 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2872,7 +2872,7 @@ def plot_grid( patch = mpatches.Patch(color=network.carriers.color[i], label=i) handles.append(patch) else: - for i in network.carriers.color.index: + for i in bus_sizes.index.get_level_values("carrier").unique(): patch = mpatches.Patch(color=network.carriers.color[i], label=i) handles.append(patch) From 00eb485a30ede8dab4a38b929725839c7cbac29b Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Mon, 27 Mar 2023 13:49:33 +0200 Subject: [PATCH 36/58] comment title of plot and use Black --- etrago/tools/plot.py | 373 +++++++++++++++++++++++++------------------ 1 file changed, 218 insertions(+), 155 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 56d5dee1c..75d951a34 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -117,7 +117,6 @@ def plot_osm(x, y, zoom, alpha=0.4): def coloring(): - colors = { "load": "red", "DC": "blue", @@ -183,7 +182,7 @@ def coloring(): "battery": "blue", "pumped_hydro": "indigo", "BEV charger": "indigo", - "others": "dimgrey" + "others": "dimgrey", } return colors @@ -222,6 +221,7 @@ def plot_line_loading_diff(networkA, networkB, timestep=0, osm=False): set_epsg_network(networkA) set_epsg_network(networkB) plot_osm(osm["x"], osm["y"], osm["zoom"]) + # new colormap to make sure 0% difference has the same color in every plot def shiftedColorMap( cmap, start=0, midpoint=0.5, stop=1.0, name="shiftedcmap" @@ -756,9 +756,11 @@ def calc_dispatch_per_carrier(network, timesteps): dispatch per carrier """ + def import_gen_from_links(network): from pypsa.networkclustering import aggregategenerators from etrago.cluster.spatial import strategies_generators + """ create gas generators from links in order to not lose them when dropping non-electric carriers @@ -857,13 +859,17 @@ def import_gen_from_links(network): ) return - + import_gen_from_links(network) ac_buses = network.buses[network.buses.carrier == "AC"].index - network.generators = network.generators[network.generators.bus.isin(ac_buses)] - network.generators_t.p = network.generators_t.p.loc[:,network.generators_t.p.columns.isin(network.generators.index)] - + network.generators = network.generators[ + network.generators.bus.isin(ac_buses) + ] + network.generators_t.p = network.generators_t.p.loc[ + :, network.generators_t.p.columns.isin(network.generators.index) + ] + index = [ (network.generators.bus[idx], network.generators.carrier[idx]) for idx in network.generators.index @@ -933,9 +939,11 @@ def calc_storage_expansion_per_bus( .sum() .reindex(network.buses.index, fill_value=0.0) ).mul(6) - - battery_distribution.index = pd.MultiIndex.from_tuples([(idx, "battery") for idx in battery_distribution.index]) - + + battery_distribution.index = pd.MultiIndex.from_tuples( + [(idx, "battery") for idx in battery_distribution.index] + ) + dist.loc[ dist.index.get_level_values("carrier") == "battery" ] = battery_distribution @@ -949,9 +957,11 @@ def calc_storage_expansion_per_bus( .sum() .reindex(network.buses.index, fill_value=0.0) ) - - h2_over_distribution.index = pd.MultiIndex.from_tuples([(idx, "H2_overground") for idx in h2_over_distribution.index]) - + + h2_over_distribution.index = pd.MultiIndex.from_tuples( + [(idx, "H2_overground") for idx in h2_over_distribution.index] + ) + dist.loc[ dist.index.get_level_values("carrier") == "H2_overground" ] = h2_over_distribution @@ -966,9 +976,11 @@ def calc_storage_expansion_per_bus( .sum() .reindex(network.buses.index, fill_value=0.0) ) - - h2_under_distribution.index = pd.MultiIndex.from_tuples([(idx, "H2_underground") for idx in h2_under_distribution.index]) - + + h2_under_distribution.index = pd.MultiIndex.from_tuples( + [(idx, "H2_underground") for idx in h2_under_distribution.index] + ) + dist.loc[ dist.index.get_level_values("carrier") == "H2_underground" ] = h2_under_distribution @@ -983,8 +995,13 @@ def calc_storage_expansion_per_bus( .sum() .reindex(network.buses.index, fill_value=0.0) ) - - rural_heat_distribution.index = pd.MultiIndex.from_tuples([(idx, "rural_heat_store") for idx in rural_heat_distribution.index]) + + rural_heat_distribution.index = pd.MultiIndex.from_tuples( + [ + (idx, "rural_heat_store") + for idx in rural_heat_distribution.index + ] + ) dist.loc[ dist.index.get_level_values("carrier") == "rural_heat_store" @@ -999,9 +1016,14 @@ def calc_storage_expansion_per_bus( .sum() .reindex(network.buses.index, fill_value=0.0) ) - - central_heat_distribution.index = pd.MultiIndex.from_tuples([(idx, "central_heat_store") for idx in central_heat_distribution.index]) - + + central_heat_distribution.index = pd.MultiIndex.from_tuples( + [ + (idx, "central_heat_store") + for idx in central_heat_distribution.index + ] + ) + dist.loc[ dist.index.get_level_values("carrier") == "central_heat_store" ] = central_heat_distribution @@ -1283,9 +1305,11 @@ def nodal_production_balance(network, timesteps, scaling=0.00001): 'green' for producer and 'red' for consumer """ + def import_gen_from_links(network): from pypsa.networkclustering import aggregategenerators from etrago.cluster.spatial import strategies_generators + """ create gas generators from links in order to not lose them when dropping non-electric carriers @@ -1384,13 +1408,17 @@ def import_gen_from_links(network): ) return - + import_gen_from_links(network) - + ac_buses = network.buses[network.buses.carrier == "AC"].index - network.generators = network.generators[network.generators.bus.isin(ac_buses)] - network.generators_t.p = network.generators_t.p.loc[:,network.generators_t.p.columns.isin(network.generators.index)] - + network.generators = network.generators[ + network.generators.bus.isin(ac_buses) + ] + network.generators_t.p = network.generators_t.p.loc[ + :, network.generators_t.p.columns.isin(network.generators.index) + ] + gen = ( mul_weighting(network, network.generators_t.p) .groupby(network.generators.bus, axis=1) @@ -1414,9 +1442,11 @@ def import_gen_from_links(network): ) bus_sizes = residual_load.abs() * scaling - bus_sizes = pd.Series(data= bus_sizes, index = network.buses.index).fillna(0) - - bus_colors = pd.Series(data= bus_colors, index = network.buses.index).fillna("grey") + bus_sizes = pd.Series(data=bus_sizes, index=network.buses.index).fillna(0) + + bus_colors = pd.Series(data=bus_colors, index=network.buses.index).fillna( + "grey" + ) return bus_sizes, bus_colors @@ -1466,7 +1496,6 @@ def storage_p_soc(network, mean="1H", filename=None): network.storage_units.p_nom_opt[sbatt].sum() > 1 and network.storage_units.p_nom_opt[shydr].sum() < 1 ): - ( network.storage_units_t.p[sbatt].resample(mean).mean().sum(axis=1) / network.storage_units.p_nom_opt[sbatt].sum() @@ -1666,7 +1695,6 @@ def mul_weighting(network, timeseries): return timeseries.mul(network.snapshot_weightings.generators, axis=0) - def calc_ac_loading(network, timesteps): """Calculates loading of AC-lines @@ -1691,7 +1719,6 @@ def calc_ac_loading(network, timesteps): ) if not network.lines_t.q0.empty: - loading_lines = ( loading_lines**2 + mul_weighting(network, network.lines_t.q0) @@ -1732,7 +1759,6 @@ def calc_dc_loading(network, timesteps): & (network.links.length == row["length"]) ] ).empty: - l = network.links.index[ (network.links.bus0 == row["bus1"]) & (network.links.bus1 == row["bus0"]) @@ -1852,7 +1878,6 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): network_c.links.p_nom_opt[i] = linked.p_nom_opt.values[0] if method == "rel": - extension_lines = ( 100 * (network_c.lines.s_nom_opt - network_c.lines.s_nom_min) @@ -1879,8 +1904,12 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): extension_links[extension_links.carrier != "DC"] = 0 extension_links = network_c.links.p_nom_opt - network_c.links.p_nom_min - extension_lines = pd.Series(data=extension_lines, index= network.lines.index).fillna(0) - extension_links = pd.Series(data=extension_links, index= network.links.index).fillna(0) + extension_lines = pd.Series( + data=extension_lines, index=network.lines.index + ).fillna(0) + extension_links = pd.Series( + data=extension_links, index=network.links.index + ).fillna(0) return network, extension_lines, extension_links @@ -2310,7 +2339,6 @@ def flexibility_usage( ) elif flexibility == "battery": - df = pd.DataFrame(index=self.network.snapshots[snapshots]) su = self.network.storage_units[ @@ -2397,13 +2425,11 @@ def plot_carrier(network, carrier_links=["AC"], carrier_buses=["AC"]): link_width = pd.Series(index=network.links.index, data=2) if len(carrier_links) > 0: - link_width.loc[~network.links.carrier.isin(carrier_links)] = 0 bus_sizes = pd.Series(index=network.buses.index, data=0.0005) if len(carrier_buses) > 0: - bus_sizes.loc[~network.buses.carrier.isin(carrier_buses)] = 0 link_colors = network.links.carrier.map(colors) @@ -2457,72 +2483,72 @@ def plot_grid( ext_min=0.1, ext_width=False, legend_entries="all", - scaling_store_expansion = { - "H2": 50, - "heat": 0.1, - "battery": 10, - } + scaling_store_expansion={ + "H2": 50, + "heat": 0.1, + "battery": 10, + }, ): """Function that plots etrago.network and results for lines and buses - Parameters - ---------- - line_colors : str - Set static line color or attribute to plot e.g. 'expansion_abs' - Current options: - 'line_loading': mean line loading in p.u. in selected timesteps - 'v_nom': nominal voltage of linesflow = pd.Series(index=network.branches().index, dtype="float64") -flow.iloc[flow.index.get_level_values("component") == "Line"] = ( - mul_weighting(network, network.lines_t.p0) - .loc[network.snapshots[timesteps]] - .sum() - / network.lines.s_nom - / rep_snapshots -).values -flow.iloc[flow.index.get_level_values("component") == "Link"] = ( - calc_dc_loading(network, timesteps) / rep_snapshots -).values -flow = flow[(flow.index.get_level_values("component")=="Line")| - (flow.index.isin(link_widths[link_colors.index.isin( - network.links[network.links.carrier=="DC"].index) - ].index, level=1))] -flow = flow.apply(lambda x: x+5 if x > 0 else x-5) - 'expansion_abs': absolute network expansion in MVA - 'expansion_rel': network expansion in p.u. of existing capacity - 'q_flow_max': maximal reactive flows - bus_sizes : float, optional - Size of buses. The default is 0.001. - bus_colors : str, optional - Set static bus color or attribute to plot. The default is 'grey'. - Current options: - 'nodal_production_balance': net producer/consumer in selected timeteps - 'storage_expansion': storage expansion per bus and technology - 'storage_distribution': installed storage units per bus - 'gen_dist': dispatch per carrier in selected timesteps - timesteps : array, optional - Timesteps consideredd in time depended plots. The default is range(2). - osm : bool or dict, e.g. {'x': [1,20], 'y': [47, 56], 'zoom' : 6} - If not False, osm is set as background - with the following settings as dict: - 'x': array of two floats, x axis boundaries (lat) - 'y': array of two floats, y axis boundaries (long) - 'zoom' : resolution of osm. The default is False. - boundaries: array - Set fixed boundaries of heatmap axis. The default is None. - filename: str or None - Save figure in this direction. The default is None. - disaggregated : bool, optional - Choose if disaggregated network is shown. The default is False. - ext_min: float - Choose minimum relative line extension shown in plot in p.u.. - ext_width: float or bool - Choose if line_width respects line extension. Turn off with 'False' or - set linear factor to decremise extension line_width. - The default is False. - - Returns - ------- - None. + Parameters + ---------- + line_colors : str + Set static line color or attribute to plot e.g. 'expansion_abs' + Current options: + 'line_loading': mean line loading in p.u. in selected timesteps + 'v_nom': nominal voltage of linesflow = pd.Series(index=network.branches().index, dtype="float64") + flow.iloc[flow.index.get_level_values("component") == "Line"] = ( + mul_weighting(network, network.lines_t.p0) + .loc[network.snapshots[timesteps]] + .sum() + / network.lines.s_nom + / rep_snapshots + ).values + flow.iloc[flow.index.get_level_values("component") == "Link"] = ( + calc_dc_loading(network, timesteps) / rep_snapshots + ).values + flow = flow[(flow.index.get_level_values("component")=="Line")| + (flow.index.isin(link_widths[link_colors.index.isin( + network.links[network.links.carrier=="DC"].index) + ].index, level=1))] + flow = flow.apply(lambda x: x+5 if x > 0 else x-5) + 'expansion_abs': absolute network expansion in MVA + 'expansion_rel': network expansion in p.u. of existing capacity + 'q_flow_max': maximal reactive flows + bus_sizes : float, optional + Size of buses. The default is 0.001. + bus_colors : str, optional + Set static bus color or attribute to plot. The default is 'grey'. + Current options: + 'nodal_production_balance': net producer/consumer in selected timeteps + 'storage_expansion': storage expansion per bus and technology + 'storage_distribution': installed storage units per bus + 'gen_dist': dispatch per carrier in selected timesteps + timesteps : array, optional + Timesteps consideredd in time depended plots. The default is range(2). + osm : bool or dict, e.g. {'x': [1,20], 'y': [47, 56], 'zoom' : 6} + If not False, osm is set as background + with the following settings as dict: + 'x': array of two floats, x axis boundaries (lat) + 'y': array of two floats, y axis boundaries (long) + 'zoom' : resolution of osm. The default is False. + boundaries: array + Set fixed boundaries of heatmap axis. The default is None. + filename: str or None + Save figure in this direction. The default is None. + disaggregated : bool, optional + Choose if disaggregated network is shown. The default is False. + ext_min: float + Choose minimum relative line extension shown in plot in p.u.. + ext_width: float or bool + Choose if line_width respects line extension. Turn off with 'False' or + set linear factor to decremise extension line_width. + The default is False. + + Returns + ------- + None. """ # Choose network or disaggregated_network @@ -2552,7 +2578,7 @@ def plot_grid( else: fig, ax = plt.subplots(figsize=(5, 5)) - + fig.set_tight_layout(True) # Set line colors @@ -2568,7 +2594,7 @@ def plot_grid( line_widths = 10 label = "line loading in p.u." plot_background_grid(network, ax) - #Only active flow direction is displayed! + # Only active flow direction is displayed! flow = pd.Series(1, index=network.branches().index, dtype="float64") flow.iloc[flow.index.get_level_values("component") == "Line"] = ( mul_weighting(network, network.lines_t.p0) @@ -2581,13 +2607,22 @@ def plot_grid( calc_dc_loading(network, timesteps) / rep_snapshots ).values - flow = flow[(flow.index.get_level_values("component")=="Line")| - (flow.index.isin(link_widths[link_widths.index.isin( - network.links[network.links.carrier=="DC"].index) - ].index, level=1))] - flow[flow<0] = -1 - flow[flow>0] = 1 - + flow = flow[ + (flow.index.get_level_values("component") == "Line") + | ( + flow.index.isin( + link_widths[ + link_widths.index.isin( + network.links[network.links.carrier == "DC"].index + ) + ].index, + level=1, + ) + ) + ] + flow[flow < 0] = -1 + flow[flow > 0] = 1 + elif line_colors == "v_nom": title = "Voltage levels" label = "v_nom in kV" @@ -2633,7 +2668,9 @@ def plot_grid( title = "Dynamic line rating" label = "MWh above nominal capacity" plot_background_grid(network, ax) - line_loading = network.lines_t.p0.mul(1 / (network.lines.s_nom_opt*network.lines.s_max_pu)) + line_loading = network.lines_t.p0.mul( + 1 / (network.lines.s_nom_opt * network.lines.s_max_pu) + ) dlr_usage = ( line_loading[line_loading.abs() > 1] .fillna(0) @@ -2646,16 +2683,15 @@ def plot_grid( line_widths = 0.5 + (line_colors / ext_width) link_colors = pd.Series(data=0, index=network.links.index) - elif line_colors == 'blue': - title = "" - label = "" - line_colors = 'blue' - link_colors = 'blue' - plot_background_grid(network, ax) - link_widths = 0 - line_widths = 0 - - + elif line_colors == "blue": + title = "" + label = "" + line_colors = "blue" + link_colors = "blue" + plot_background_grid(network, ax) + link_widths = 0 + line_widths = 0 + else: logger.warning("line_color {} undefined".format(line_colors)) @@ -2671,27 +2707,39 @@ def plot_grid( bus_unit = "TWh" elif bus_colors == "storage_expansion": if not isinstance(scaling_store_expansion, dict): - raise Exception("""To plot storage_expansion, the argument scaling_store_expansion must be a dictionary like: + raise Exception( + """To plot storage_expansion, the argument scaling_store_expansion must be a dictionary like: {"H2": 50, "heat": 0.1, - "battery": 10}""") + "battery": 10}""" + ) bus_scaling = bus_sizes bus_sizes = bus_scaling * calc_storage_expansion_per_bus(network) for store_carrier in ["H2", "heat", "battery"]: - bus_sizes[bus_sizes.index.get_level_values('carrier').str.contains(store_carrier)] *= scaling_store_expansion[store_carrier] + bus_sizes[ + bus_sizes.index.get_level_values("carrier").str.contains( + store_carrier + ) + ] *= scaling_store_expansion[store_carrier] bus_legend = "Storage expansion" bus_unit = "GW" elif bus_colors == "h2_battery_storage_expansion": bus_scaling = bus_sizes - bus_sizes = bus_scaling * calc_storage_expansion_per_bus(network, carriers=["battery", "H2_overground", "H2_underground"]) - if (("battery" not in scaling_store_expansion.keys()) | - ("H2_overground" not in scaling_store_expansion.keys()) | - ("H2_underground" not in scaling_store_expansion.keys())): - raise Exception("""To plot h2_battery_storage_expansion, the argument scaling_store_expansion must be a dictionary like: + bus_sizes = bus_scaling * calc_storage_expansion_per_bus( + network, carriers=["battery", "H2_overground", "H2_underground"] + ) + if ( + ("battery" not in scaling_store_expansion.keys()) + | ("H2_overground" not in scaling_store_expansion.keys()) + | ("H2_underground" not in scaling_store_expansion.keys()) + ): + raise Exception( + """To plot h2_battery_storage_expansion, the argument scaling_store_expansion must be a dictionary like: {"H2_overground": 1, "H2_underground": 1, - "battery": 1,}""") - + "battery": 1,}""" + ) + for store_carrier in ["battery", "H2_overground", "H2_underground"]: bus_sizes[ bus_sizes.index.get_level_values("carrier").str.contains( @@ -2734,15 +2782,17 @@ def plot_grid( .mul(network.snapshot_weightings.generators, axis=0) .sum() ) - bus_sizes = bus_scaling * flex_links.groupby(["bus0", "carrier"]).p0_sum.sum() + bus_sizes = ( + bus_scaling * flex_links.groupby(["bus0", "carrier"]).p0_sum.sum() + ) bus_unit = "TWh" bus_legend = "flexibility_usage" elif bus_colors == "h2_storage_expansion": bus_scaling = bus_sizes bus_sizes = bus_scaling * calc_storage_expansion_per_bus(network) bus_sizes = bus_sizes.reset_index() - bus_sizes = bus_sizes[bus_sizes.carrier.str.contains('H2')] - bus_sizes.set_index(['bus','carrier'],inplace=True) + bus_sizes = bus_sizes[bus_sizes.carrier.str.contains("H2")] + bus_sizes.set_index(["bus", "carrier"], inplace=True) bus_legend = "Storage expansion" bus_unit = "GW" elif ( @@ -2781,14 +2831,14 @@ def plot_grid( line_widths=line_widths, link_widths=link_widths, flow=flow, - title=title, + # title=title, geomap=False, projection=ccrs.PlateCarree(), color_geomap=True, boundaries=[-2.5, 16, 46.8, 58], ) else: - ll =network.plot( + ll = network.plot( line_colors=line_colors, link_colors=link_colors, line_cmap=plt.cm.jet, @@ -2798,11 +2848,11 @@ def plot_grid( line_widths=line_widths, link_widths=link_widths, flow=flow, - title=title, + # title=title, geomap=False, boundaries=[-2.5, 16, 46.8, 58], ) - + # legends for bus sizes and colors if bus_legend: handles = [] @@ -2812,11 +2862,17 @@ def plot_grid( if bus_legend == "Storage expansion": legend_entries = list(scaling_store_expansion.keys()) if bus_legend == "Battery and H2 storage expansion": - legend_entries = ["battery", "H2_overground", "H2_underground"] + legend_entries = [ + "battery", + "H2_overground", + "H2_underground", + ] for i in legend_entries: try: max_value = bus_sizes[ - bus_sizes.index.get_level_values("carrier").str.contains(i) + bus_sizes.index.get_level_values( + "carrier" + ).str.contains(i) ].max() except: max_value = bus_sizes.max() @@ -2833,9 +2889,7 @@ def plot_grid( ) else: max_value = bus_sizes.max() - labels.append( - f"{round(max_value / bus_scaling /1000, 0)} GWh " - ) + labels.append(f"{round(max_value / bus_scaling /1000, 0)} GWh ") handles.append( make_legend_circles_for( [max_value], @@ -2853,14 +2907,13 @@ def plot_grid( framealpha=1.0, title=bus_legend, handler_map=make_handler_map_to_scale_circles_as_in(ax), - prop={'size': 8} + prop={"size": 8}, ) ax.add_artist(l2) - plt.setp(l2.get_title(),fontsize='9') + plt.setp(l2.get_title(), fontsize="9") if not scaling_store_expansion: - handles = [] if bus_legend == "Nodal production balance": positive = mpatches.Patch(color="green", label="generation") @@ -2869,27 +2922,33 @@ def plot_grid( elif legend_entries != "all": for i in legend_entries: - patch = mpatches.Patch(color=network.carriers.color[i], label=i) + patch = mpatches.Patch( + color=network.carriers.color[i], label=i + ) handles.append(patch) else: for i in bus_sizes.index.get_level_values("carrier").unique(): - patch = mpatches.Patch(color=network.carriers.color[i], label=i) + patch = mpatches.Patch( + color=network.carriers.color[i], label=i + ) handles.append(patch) - + l3 = plt.legend( - handles=handles, loc="upper left", ncol=2, bbox_to_anchor=(0, 0) + handles=handles, + loc="upper left", + ncol=2, + bbox_to_anchor=(0, 0), ) ax.add_artist(l3) if type(line_colors) != str: - # Set fixed boundaries if selected in parameters if not boundaries: boundaries = [ min(line_colors.min(), link_colors.min()), max(line_colors.max(), link_colors.max()), ] - + # Create ticks for legend v = np.linspace(boundaries[0], boundaries[1], 101) for l_collection in ll: @@ -2897,8 +2956,12 @@ def plot_grid( # colorbar for line heatmap cb = plt.colorbar( - ll[1], values=v, ticks=v[0:101:10], fraction=0.028, pad=0.04, - ) + ll[1], + values=v, + ticks=v[0:101:10], + fraction=0.028, + pad=0.04, + ) # Set legend label cb.set_label(label) @@ -3707,7 +3770,7 @@ def plot_heat_summary(self, t_resolution="20H", stacked=True, save_path=False): data.resample(t_resolution).mean().plot( ax=ax, label=i, legend=True ) - + heat_store_dispatch_hb.resample(t_resolution).mean().plot.line( ax=ax, legend=True, From db21a490ca6b43a6f2868af71a306e7dc7b34319 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Mon, 27 Mar 2023 15:41:43 +0200 Subject: [PATCH 37/58] apply flake8 --- etrago/tools/plot.py | 156 ++++++++++++++++++++----------------------- 1 file changed, 72 insertions(+), 84 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 75d951a34..968feb6c2 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -21,12 +21,17 @@ """ Plot.py defines functions necessary to plot results of eTraGo. """ -from math import log10, sqrt +from math import sqrt import logging import os from matplotlib import pyplot as plt +from matplotlib.legend_handler import HandlerPatch +from matplotlib.patches import Circle, Ellipse from pyproj import Proj, transform +from pypsa.plot import draw_map_cartopy +from shapely.geometry import LineString, Point +import geopandas as gpd import matplotlib import matplotlib.patches as mpatches import numpy as np @@ -35,15 +40,10 @@ cartopy_present = True try: - import cartopy import cartopy.crs as ccrs - import cartopy.mpl.geoaxes - import requests except ImportError: cartopy_present = False -from pypsa.plot import draw_map_cartopy -from shapely.geometry import LineString, MultiPoint, Point, Polygon -import geopandas as gpd + logger = logging.getLogger(__name__) @@ -216,7 +216,7 @@ def plot_line_loading_diff(networkA, networkB, timestep=0, osm=False): 'y': array of two floats, y axis boundaries (long) 'zoom' : resolution of osm """ - if osm != False: + if osm is not False: if set_epsg_network.counter == 0: set_epsg_network(networkA) set_epsg_network(networkB) @@ -347,7 +347,7 @@ def network_expansion_diff( 'zoom' : resolution of osm """ - if osm != False: + if osm is not False: if set_epsg_network.counter == 0: set_epsg_network(networkA) set_epsg_network(networkB) @@ -648,7 +648,7 @@ def plot_voltage(network, boundaries=[], osm=False): ------- Plot """ - if osm != False: + if osm is not False: if set_epsg_network.counter == 0: set_epsg_network(network) plot_osm(osm["x"], osm["y"], osm["zoom"]) @@ -759,6 +759,7 @@ def calc_dispatch_per_carrier(network, timesteps): def import_gen_from_links(network): from pypsa.networkclustering import aggregategenerators + from etrago.cluster.spatial import strategies_generators """ @@ -1182,11 +1183,11 @@ def nodal_gen_dispatch( 'zoom' : resolution of osm """ - if osm != False: + if osm is not False: if set_epsg_network.counter == 0: set_epsg_network(network) fig, ax = plot_osm(osm["x"], osm["y"], osm["zoom"]) - elif (osm == False) and cartopy_present: + elif (osm is False) and cartopy_present: fig, ax = plt.subplots( subplot_kw={"projection": ccrs.PlateCarree()}, figsize=(5, 5) ) @@ -1308,6 +1309,7 @@ def nodal_production_balance(network, timesteps, scaling=0.00001): def import_gen_from_links(network): from pypsa.networkclustering import aggregategenerators + from etrago.cluster.spatial import strategies_generators """ @@ -1607,15 +1609,6 @@ def storage_soc_sorted(network, filename=None): & (network.storage_units.max_hours == 168) ] - cap_batt = ( - network.storage_units.max_hours[sbatt] - * network.storage_units.p_nom_opt[sbatt] - ).sum() - cap_hydr = ( - network.storage_units.max_hours[shydr] - * network.storage_units.p_nom_opt[shydr] - ).sum() - fig, ax = plt.subplots(1, 1) if ( @@ -1759,13 +1752,13 @@ def calc_dc_loading(network, timesteps): & (network.links.length == row["length"]) ] ).empty: - l = network.links.index[ + links_df = network.links.index[ (network.links.bus0 == row["bus1"]) & (network.links.bus1 == row["bus0"]) & (network.links.length == row["length"]) ] - network.links.at[i, "linked_to"] = l.values[0] + network.links.at[i, "linked_to"] = links_df.values[0] network.links.linked_to = network.links.linked_to.astype(str) # Set p_nom_max and line_loading for one directional links @@ -1978,26 +1971,26 @@ def demand_side_management(self, buses, snapshots, agg="5h", used=False): """ df = pd.DataFrame(index=self.network.snapshots[snapshots]) - l = self.network.links[ + link = self.network.links[ (self.network.links.carrier == "dsm") & (self.network.links.bus0.isin(buses)) ] s = self.network.stores[ (self.network.stores.carrier == "dsm") - & (self.network.stores.bus.isin(l.bus1.values)) + & (self.network.stores.bus.isin(link.bus1.values)) ] df["p_min"] = ( - self.network.links_t.p_min_pu[l.index] - .mul(l.p_nom, axis=1) + self.network.links_t.p_min_pu[link.index] + .mul(link.p_nom, axis=1) .sum(axis=1) .resample(agg) .mean() .iloc[snapshots] ) df["p_max"] = ( - self.network.links_t.p_max_pu[l.index] - .mul(l.p_nom, axis=1) + self.network.links_t.p_max_pu[link.index] + .mul(link.p_nom, axis=1) .sum(axis=1) .resample(agg) .mean() @@ -2019,7 +2012,7 @@ def demand_side_management(self, buses, snapshots, agg="5h", used=False): if used: df["p"] = ( - self.network.links_t.p0[l.index] + self.network.links_t.p0[link.index] .clip(lower=0) .sum(axis=1) .resample(agg) @@ -2288,7 +2281,8 @@ def flexibility_usage( snapshots : list, optional Considered snapshots, if empty all are considered. The default is []. buses : list, optional - Considered components at AC buses, if empty all are considered. The default is []. + Considered components at AC buses, if empty all are considered. + The default is []. pre_path : str, optional State of and where you want to store the figure. The default is None. @@ -2302,9 +2296,6 @@ def flexibility_usage( colors["h2_store"] = colors["H2_underground"] colors["heat"] = colors["central_heat_store"] - potential = pd.DataFrame(index=self.network.snapshots[snapshots]) - used = pd.DataFrame(index=self.network.snapshots[snapshots]) - if not buses: buses = self.network.buses.index @@ -2497,22 +2488,7 @@ def plot_grid( Set static line color or attribute to plot e.g. 'expansion_abs' Current options: 'line_loading': mean line loading in p.u. in selected timesteps - 'v_nom': nominal voltage of linesflow = pd.Series(index=network.branches().index, dtype="float64") - flow.iloc[flow.index.get_level_values("component") == "Line"] = ( - mul_weighting(network, network.lines_t.p0) - .loc[network.snapshots[timesteps]] - .sum() - / network.lines.s_nom - / rep_snapshots - ).values - flow.iloc[flow.index.get_level_values("component") == "Link"] = ( - calc_dc_loading(network, timesteps) / rep_snapshots - ).values - flow = flow[(flow.index.get_level_values("component")=="Line")| - (flow.index.isin(link_widths[link_colors.index.isin( - network.links[network.links.carrier=="DC"].index) - ].index, level=1))] - flow = flow.apply(lambda x: x+5 if x > 0 else x-5) + 'v_nom': nominal voltage of lines 'expansion_abs': absolute network expansion in MVA 'expansion_rel': network expansion in p.u. of existing capacity 'q_flow_max': maximal reactive flows @@ -2521,12 +2497,14 @@ def plot_grid( bus_colors : str, optional Set static bus color or attribute to plot. The default is 'grey'. Current options: - 'nodal_production_balance': net producer/consumer in selected timeteps + 'nodal_production_balance': net producer/consumer in + selected timeteps 'storage_expansion': storage expansion per bus and technology 'storage_distribution': installed storage units per bus 'gen_dist': dispatch per carrier in selected timesteps timesteps : array, optional - Timesteps consideredd in time depended plots. The default is range(2). + Timesteps consideredd in time depended plots. The default + is range(2). osm : bool or dict, e.g. {'x': [1,20], 'y': [47, 56], 'zoom' : 6} If not False, osm is set as background with the following settings as dict: @@ -2542,8 +2520,8 @@ def plot_grid( ext_min: float Choose minimum relative line extension shown in plot in p.u.. ext_width: float or bool - Choose if line_width respects line extension. Turn off with 'False' or - set linear factor to decremise extension line_width. + Choose if line_width respects line extension. Turn off with + 'False' or set linear factor to decremise extension line_width. The default is False. Returns @@ -2562,16 +2540,17 @@ def plot_grid( # Set default values flow = None + title = "" line_widths = 2 link_widths = 0 # Plot osm map in background - if osm != False: + if osm is not False: if network.srid == 4326: set_epsg_network(network) fig, ax = plot_osm(osm["x"], osm["y"], osm["zoom"]) - elif (osm == False) and cartopy_present: + elif (osm is False) and cartopy_present: fig, ax = plt.subplots( subplot_kw={"projection": ccrs.PlateCarree()}, figsize=(5, 5) ) @@ -2636,7 +2615,7 @@ def plot_grid( network, method="abs", ext_min=ext_min ) plot_background_grid(all_network, ax) - if ext_width != False: + if ext_width is not False: line_widths = 0.5 + (line_colors / ext_width) link_widths = 0.5 + (line_colors / ext_width) else: @@ -2653,7 +2632,7 @@ def plot_grid( network, method="rel", ext_min=ext_min ) plot_background_grid(all_network, ax) - if ext_width != False: + if ext_width is not False: line_widths = 0.5 + (line_colors / ext_width) link_widths = 0.5 + (link_colors / ext_width) elif line_colors == "q_flow_max": @@ -2679,7 +2658,7 @@ def plot_grid( .sum() ) line_colors = dlr_usage - if ext_width != False: + if ext_width is not False: line_widths = 0.5 + (line_colors / ext_width) link_colors = pd.Series(data=0, index=network.links.index) @@ -2708,7 +2687,8 @@ def plot_grid( elif bus_colors == "storage_expansion": if not isinstance(scaling_store_expansion, dict): raise Exception( - """To plot storage_expansion, the argument scaling_store_expansion must be a dictionary like: + """To plot storage_expansion, the argument\ + scaling_store_expansion must be a dictionary like: {"H2": 50, "heat": 0.1, "battery": 10}""" @@ -2734,7 +2714,8 @@ def plot_grid( | ("H2_underground" not in scaling_store_expansion.keys()) ): raise Exception( - """To plot h2_battery_storage_expansion, the argument scaling_store_expansion must be a dictionary like: + """To plot h2_battery_storage_expansion, the argument\ + scaling_store_expansion must be a dictionary like: {"H2_overground": 1, "H2_underground": 1, "battery": 1,}""" @@ -2831,7 +2812,7 @@ def plot_grid( line_widths=line_widths, link_widths=link_widths, flow=flow, - # title=title, + title=title, geomap=False, projection=ccrs.PlateCarree(), color_geomap=True, @@ -2848,7 +2829,7 @@ def plot_grid( line_widths=line_widths, link_widths=link_widths, flow=flow, - # title=title, + title=title, geomap=False, boundaries=[-2.5, 16, 46.8, 58], ) @@ -2874,7 +2855,7 @@ def plot_grid( "carrier" ).str.contains(i) ].max() - except: + except KeyError: max_value = bus_sizes.max() handles.append( make_legend_circles_for( @@ -2884,8 +2865,9 @@ def plot_grid( )[0] ) labels.append( - f"{round(max_value / bus_scaling / scaling_store_expansion[i]/1000, 0).astype(int)} GWh " - + i + f""" + {round(max_value/bus_scaling/scaling_store_expansion[i]/ + 1000, 0).astype(int)} {bus_unit} """ + i ) else: max_value = bus_sizes.max() @@ -2979,10 +2961,8 @@ def plot_grid( set_epsg_network.counter = 0 -### the following functions are copied from pypsa-eur-sec ### -### see here: https://github.com/PyPSA/pypsa-eur-sec/blob/master/scripts/plot_network.py -from matplotlib.legend_handler import HandlerPatch -from matplotlib.patches import Circle, Ellipse +# the following functions are copied from pypsa-eur-sec. see: +# https://github.com/PyPSA/pypsa-eur-sec/blob/master/scripts/plot_network.py def make_handler_map_to_scale_circles_as_in(ax, dont_resize_actively=False): @@ -3191,7 +3171,8 @@ def plot_gas_generation( self : :class:`Etrago Overall container of Etrago t_resolution : str, optional - sets the resampling rate of timeseries data to allow for smoother line plots + sets the resampling rate of timeseries data to allow for smoother + line plots save_path : bool, optional Path to save the generated plot. The default is False. @@ -3256,10 +3237,12 @@ def plot_gas_summary(self, t_resolution="20H", stacked=True, save_path=False): self : :class:`Etrago Overall container of Etrago t_resolution : str, optional - sets the resampling rate of timeseries data to allow for smoother line plots + sets the resampling rate of timeseries data to allow for smoother + line plots stacked : bool, optional - If True all TS data will be shown as stacked area plot. Total gas generation - will then also be plotted to check for matching demand and generation. + If True all TS data will be shown as stacked area plot. Total gas + generation will then also be plotted to check for matching demand and + generation. save_path : bool, optional Path to save the generated plot. The default is False. @@ -3410,7 +3393,8 @@ def plot_h2_generation(self, t_resolution="20H", save_path=False): self : :class:`Etrago Overall container of Etrago t_resolution : str, optional - sets the resampling rate of timeseries data to allow for smoother line plots + sets the resampling rate of timeseries data to allow for smoother + line plots save_path : bool, optional Path to save the generated plot. The default is False. @@ -3468,10 +3452,12 @@ def plot_h2_summary(self, t_resolution="20H", stacked=True, save_path=False): self : :class:`Etrago Overall container of Etrago t_resolution : str, optional - sets the resampling rate of timeseries data to allow for smoother line plots + sets the resampling rate of timeseries data to allow for smoother + line plots stacked : bool, optional - If True all TS data will be shown as stacked area plot. Total H2 generation - will then also be plotted to check for matching demand and generation. + If True all TS data will be shown as stacked area plot. Total H2 + generation will then also be plotted to check for matching demand and + generation. save_path : bool, optional Path to save the generated plot. The default is False. @@ -3480,7 +3466,6 @@ def plot_h2_summary(self, t_resolution="20H", stacked=True, save_path=False): None. """ - colors = coloring() rel_h2_links = ["H2_feedin", "H2_to_CH4", "H2_to_power"] rel_h2_loads = ["H2_for_industry", "H2_hgv_load"] @@ -3593,7 +3578,8 @@ def plot_heat_loads(self, t_resolution="20H", save_path=False): self : :class:`Etrago Overall container of Etrago t_resolution : str, optional - sets the resampling rate of timeseries data to allow for smoother line plots + sets the resampling rate of timeseries data to allow for smoother + line plots save_path : bool, optional Path to save the generated plot. The default is False. @@ -3642,10 +3628,12 @@ def plot_heat_summary(self, t_resolution="20H", stacked=True, save_path=False): self : :class:`Etrago Overall container of Etrago t_resolution : str, optional - sets the resampling rate of timeseries data to allow for smoother line plots + sets the resampling rate of timeseries data to allow for smoother + line plots stacked : bool, optional - If True all TS data will be shown as stacked area plot. Total heat demand - will then also be plotted to check for matching generation and demand. + If True all TS data will be shown as stacked area plot. Total heat + demand will then also be plotted to check for matching generation and + demand. save_path : bool, optional Path to save the generated plot. The default is False. @@ -3717,7 +3705,7 @@ def plot_heat_summary(self, t_resolution="20H", stacked=True, save_path=False): / 1e3 ) - if stacked == True: + if stacked: data = pd.DataFrame(-(data.sum(axis=1))) data = data.rename(columns={0: heat_gen_techs[0]}) From 7eddadfac2b046c466c756a9b89b2ef155e7e71a Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 28 Mar 2023 09:10:07 +0200 Subject: [PATCH 38/58] update docstrings plot_grid --- etrago/tools/plot.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 968feb6c2..f58b3daa9 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2492,6 +2492,8 @@ def plot_grid( 'expansion_abs': absolute network expansion in MVA 'expansion_rel': network expansion in p.u. of existing capacity 'q_flow_max': maximal reactive flows + 'dlr': energy above nominal capacity + 'grey': plot all lines and DC linkd grey colored bus_sizes : float, optional Size of buses. The default is 0.001. bus_colors : str, optional @@ -2499,9 +2501,13 @@ def plot_grid( Current options: 'nodal_production_balance': net producer/consumer in selected timeteps - 'storage_expansion': storage expansion per bus and technology + 'storage_expansion': storage expansion per bus and technology. + 'h2_battery_storage_expansion': storage expansion per bus and + technology for underground and overground H2 and batteries. 'storage_distribution': installed storage units per bus 'gen_dist': dispatch per carrier in selected timesteps + 'PowerToH2': location and sizes of electrolizers + 'flexibility_usage': use of DSM and BEV charger timesteps : array, optional Timesteps consideredd in time depended plots. The default is range(2). @@ -2523,7 +2529,13 @@ def plot_grid( Choose if line_width respects line extension. Turn off with 'False' or set linear factor to decremise extension line_width. The default is False. - + legend_entries : list, optional + Set the legends for buses to be plotted. The default is 'all'. + scaling_store_expansion : dict, optional + Set scaling values to be used per technology for the plots + storage_expansion and h2_battery_storage_expansion. The default is + {"H2": 50, "heat": 0.1, "battery": 10} + Returns ------- None. From ef95e2ca648ac652a62b02cd8c89c975a52e8d54 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 28 Mar 2023 09:11:02 +0200 Subject: [PATCH 39/58] change line colors basic to grey --- etrago/tools/plot.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index f58b3daa9..1e1ad9b99 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2674,11 +2674,11 @@ def plot_grid( line_widths = 0.5 + (line_colors / ext_width) link_colors = pd.Series(data=0, index=network.links.index) - elif line_colors == "blue": + elif line_colors == "grey": title = "" label = "" - line_colors = "blue" - link_colors = "blue" + line_colors = "grey" + link_colors = "grey" plot_background_grid(network, ax) link_widths = 0 line_widths = 0 From 28204f1d071bbcf1fa06b4f79540fe1a57d11f56 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 28 Mar 2023 09:58:23 +0200 Subject: [PATCH 40/58] extract the function import_gen_from_links from pf_post_lopf --- etrago/tools/execute.py | 200 ++++++++++++++++++++-------------------- 1 file changed, 101 insertions(+), 99 deletions(-) diff --git a/etrago/tools/execute.py b/etrago/tools/execute.py index 0e8c688cc..3b7eb17a8 100755 --- a/etrago/tools/execute.py +++ b/etrago/tools/execute.py @@ -391,6 +391,107 @@ def dispatch_disaggregation(self): logger.info("Time for LOPF [min]: {}".format(round(z, 2))) +def import_gen_from_links(network): + """ + create gas generators from links in order to not lose them when + dropping non-electric carriers + """ + # Discard all generators < 1kW + discard_gen = network.links[network.links["p_nom"] <= 0.001].index + network.links.drop(discard_gen, inplace=True) + for df in network.links_t: + if not network.links_t[df].empty: + network.links_t[df].drop( + columns=discard_gen.values, inplace=True, errors="ignore" + ) + + gas_to_add = network.links[ + network.links.carrier.isin( + [ + "central_gas_CHP", + "OCGT", + "H2_to_power", + "industrial_gas_CHP", + ] + ) + ].copy() + + # Drop generators from the links table + network.links.drop(gas_to_add.index, inplace=True) + + gas_to_add.rename(columns={"bus1": "bus"}, inplace=True) + + # Create generators' names like in network.generators + gas_to_add["Generator"] = ( + gas_to_add["bus"] + " " + gas_to_add.index + gas_to_add["carrier"] + ) + gas_to_add_orig = gas_to_add.copy() + gas_to_add.set_index("Generator", drop=True, inplace=True) + gas_to_add = gas_to_add[ + gas_to_add.columns[ + gas_to_add.columns.isin(network.generators.columns) + ] + ] + + network.import_components_from_dataframe(gas_to_add, "Generator") + + # Dealing with generators_t + columns_new = network.links_t.p1.columns[ + network.links_t.p1.columns.isin(gas_to_add_orig.index) + ] + + new_gen_t = network.links_t.p1[columns_new] * -1 + new_gen_t.rename(columns=gas_to_add_orig["Generator"], inplace=True) + network.generators_t.p = network.generators_t.p.join(new_gen_t) + + # Drop generators from the links_t table + for df in network.links_t: + if not network.links_t[df].empty: + network.links_t[df].drop( + columns=gas_to_add_orig.index, + inplace=True, + errors="ignore", + ) + + # Group generators per bus if needed + if not ( + network.generators.groupby(["bus", "carrier"]).p_nom.count() == 1 + ).all(): + network.generators["weight"] = network.generators.p_nom + df, df_t = aggregategenerators( + network, + busmap=pd.Series( + index=network.buses.index, data=network.buses.index + ), + custom_strategies=strategies_generators(), + ) + + # Keep control arguments from generators + control = network.generators.groupby( + ["bus", "carrier"] + ).control.first() + control.index = ( + control.index.get_level_values(0) + + " " + + control.index.get_level_values(1) + ) + df.control = control + + # Drop non-aggregated generators + network.mremove("Generator", network.generators.index) + + # Insert aggregated generators and time series + network.import_components_from_dataframe(df, "Generator") + + for attr, data in df_t.items(): + if not data.empty: + network.import_series_from_dataframe( + data, "Generator", attr + ) + + return + + def run_pf_post_lopf(self): """Functions that runs pf_post_lopf accordning to arguments @@ -542,105 +643,6 @@ def drop_foreign_components(network): return foreign_bus, foreign_comp, foreign_series - def import_gen_from_links(network): - """ - create gas generators from links in order to not lose them when - dropping non-electric carriers - """ - # Discard all generators < 1kW - discard_gen = network.links[network.links["p_nom"] <= 0.001].index - network.links.drop(discard_gen, inplace=True) - for df in network.links_t: - if not network.links_t[df].empty: - network.links_t[df].drop( - columns=discard_gen.values, inplace=True, errors="ignore" - ) - - gas_to_add = network.links[ - network.links.carrier.isin( - [ - "central_gas_CHP", - "OCGT", - "H2_to_power", - "industrial_gas_CHP", - ] - ) - ].copy() - - # Drop generators from the links table - network.links.drop(gas_to_add.index, inplace=True) - - gas_to_add.rename(columns={"bus1": "bus"}, inplace=True) - - # Create generators' names like in network.generators - gas_to_add["Generator"] = ( - gas_to_add["bus"] + " " + gas_to_add.index + gas_to_add["carrier"] - ) - gas_to_add_orig = gas_to_add.copy() - gas_to_add.set_index("Generator", drop=True, inplace=True) - gas_to_add = gas_to_add[ - gas_to_add.columns[ - gas_to_add.columns.isin(network.generators.columns) - ] - ] - - network.import_components_from_dataframe(gas_to_add, "Generator") - - # Dealing with generators_t - columns_new = network.links_t.p1.columns[ - network.links_t.p1.columns.isin(gas_to_add_orig.index) - ] - - new_gen_t = network.links_t.p1[columns_new] * -1 - new_gen_t.rename(columns=gas_to_add_orig["Generator"], inplace=True) - network.generators_t.p = network.generators_t.p.join(new_gen_t) - - # Drop generators from the links_t table - for df in network.links_t: - if not network.links_t[df].empty: - network.links_t[df].drop( - columns=gas_to_add_orig.index, - inplace=True, - errors="ignore", - ) - - # Group generators per bus if needed - if not ( - network.generators.groupby(["bus", "carrier"]).p_nom.count() == 1 - ).all(): - network.generators["weight"] = network.generators.p_nom - df, df_t = aggregategenerators( - network, - busmap=pd.Series( - index=network.buses.index, data=network.buses.index - ), - custom_strategies=strategies_generators(), - ) - - # Keep control arguments from generators - control = network.generators.groupby( - ["bus", "carrier"] - ).control.first() - control.index = ( - control.index.get_level_values(0) - + " " - + control.index.get_level_values(1) - ) - df.control = control - - # Drop non-aggregated generators - network.mremove("Generator", network.generators.index) - - # Insert aggregated generators and time series - network.import_components_from_dataframe(df, "Generator") - - for attr, data in df_t.items(): - if not data.empty: - network.import_series_from_dataframe( - data, "Generator", attr - ) - - return x = time.time() network = etrago.network From 5f1d03eb2bfd85106b06488536ac9d50981b9310 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 28 Mar 2023 10:28:07 +0200 Subject: [PATCH 41/58] delete duplicated functions --- etrago/tools/plot.py | 209 +------------------------------------------ 1 file changed, 1 insertion(+), 208 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 1e1ad9b99..25364b1c4 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -31,6 +31,7 @@ from pyproj import Proj, transform from pypsa.plot import draw_map_cartopy from shapely.geometry import LineString, Point +from etrago.tools.execute import import_gen_from_links import geopandas as gpd import matplotlib import matplotlib.patches as mpatches @@ -757,110 +758,6 @@ def calc_dispatch_per_carrier(network, timesteps): """ - def import_gen_from_links(network): - from pypsa.networkclustering import aggregategenerators - - from etrago.cluster.spatial import strategies_generators - - """ - create gas generators from links in order to not lose them when - dropping non-electric carriers - """ - # Discard all generators < 1kW - discard_gen = network.links[network.links["p_nom"] <= 0.001].index - network.links.drop(discard_gen, inplace=True) - for df in network.links_t: - if not network.links_t[df].empty: - network.links_t[df].drop( - columns=discard_gen.values, inplace=True, errors="ignore" - ) - - gas_to_add = network.links[ - network.links.carrier.isin( - [ - "central_gas_CHP", - "OCGT", - "H2_to_power", - "industrial_gas_CHP", - ] - ) - ].copy() - - # Drop generators from the links table - network.links.drop(gas_to_add.index, inplace=True) - - gas_to_add.rename(columns={"bus1": "bus"}, inplace=True) - - # Create generators' names like in network.generators - gas_to_add["Generator"] = ( - gas_to_add["bus"] + " " + gas_to_add.index + gas_to_add["carrier"] - ) - gas_to_add_orig = gas_to_add.copy() - gas_to_add.set_index("Generator", drop=True, inplace=True) - gas_to_add = gas_to_add[ - gas_to_add.columns[ - gas_to_add.columns.isin(network.generators.columns) - ] - ] - - network.import_components_from_dataframe(gas_to_add, "Generator") - - # Dealing with generators_t - columns_new = network.links_t.p1.columns[ - network.links_t.p1.columns.isin(gas_to_add_orig.index) - ] - - new_gen_t = network.links_t.p1[columns_new] * -1 - new_gen_t.rename(columns=gas_to_add_orig["Generator"], inplace=True) - network.generators_t.p = network.generators_t.p.join(new_gen_t) - - # Drop generators from the links_t table - for df in network.links_t: - if not network.links_t[df].empty: - network.links_t[df].drop( - columns=gas_to_add_orig.index, - inplace=True, - errors="ignore", - ) - - # Group generators per bus if needed - if not ( - network.generators.groupby(["bus", "carrier"]).p_nom.count() == 1 - ).all(): - network.generators["weight"] = network.generators.p_nom - df, df_t = aggregategenerators( - network, - busmap=pd.Series( - index=network.buses.index, data=network.buses.index - ), - custom_strategies=strategies_generators(), - ) - - # Keep control arguments from generators - control = network.generators.groupby( - ["bus", "carrier"] - ).control.first() - control.index = ( - control.index.get_level_values(0) - + " " - + control.index.get_level_values(1) - ) - df.control = control - - # Drop non-aggregated generators - network.mremove("Generator", network.generators.index) - - # Insert aggregated generators and time series - network.import_components_from_dataframe(df, "Generator") - - for attr, data in df_t.items(): - if not data.empty: - network.import_series_from_dataframe( - data, "Generator", attr - ) - - return - import_gen_from_links(network) ac_buses = network.buses[network.buses.carrier == "AC"].index @@ -1307,110 +1204,6 @@ def nodal_production_balance(network, timesteps, scaling=0.00001): """ - def import_gen_from_links(network): - from pypsa.networkclustering import aggregategenerators - - from etrago.cluster.spatial import strategies_generators - - """ - create gas generators from links in order to not lose them when - dropping non-electric carriers - """ - # Discard all generators < 1kW - discard_gen = network.links[network.links["p_nom"] <= 0.001].index - network.links.drop(discard_gen, inplace=True) - for df in network.links_t: - if not network.links_t[df].empty: - network.links_t[df].drop( - columns=discard_gen.values, inplace=True, errors="ignore" - ) - - gas_to_add = network.links[ - network.links.carrier.isin( - [ - "central_gas_CHP", - "OCGT", - "H2_to_power", - "industrial_gas_CHP", - ] - ) - ].copy() - - # Drop generators from the links table - network.links.drop(gas_to_add.index, inplace=True) - - gas_to_add.rename(columns={"bus1": "bus"}, inplace=True) - - # Create generators' names like in network.generators - gas_to_add["Generator"] = ( - gas_to_add["bus"] + " " + gas_to_add.index + gas_to_add["carrier"] - ) - gas_to_add_orig = gas_to_add.copy() - gas_to_add.set_index("Generator", drop=True, inplace=True) - gas_to_add = gas_to_add[ - gas_to_add.columns[ - gas_to_add.columns.isin(network.generators.columns) - ] - ] - - network.import_components_from_dataframe(gas_to_add, "Generator") - - # Dealing with generators_t - columns_new = network.links_t.p1.columns[ - network.links_t.p1.columns.isin(gas_to_add_orig.index) - ] - - new_gen_t = network.links_t.p1[columns_new] * -1 - new_gen_t.rename(columns=gas_to_add_orig["Generator"], inplace=True) - network.generators_t.p = network.generators_t.p.join(new_gen_t) - - # Drop generators from the links_t table - for df in network.links_t: - if not network.links_t[df].empty: - network.links_t[df].drop( - columns=gas_to_add_orig.index, - inplace=True, - errors="ignore", - ) - - # Group generators per bus if needed - if not ( - network.generators.groupby(["bus", "carrier"]).p_nom.count() == 1 - ).all(): - network.generators["weight"] = network.generators.p_nom - df, df_t = aggregategenerators( - network, - busmap=pd.Series( - index=network.buses.index, data=network.buses.index - ), - custom_strategies=strategies_generators(), - ) - - # Keep control arguments from generators - control = network.generators.groupby( - ["bus", "carrier"] - ).control.first() - control.index = ( - control.index.get_level_values(0) - + " " - + control.index.get_level_values(1) - ) - df.control = control - - # Drop non-aggregated generators - network.mremove("Generator", network.generators.index) - - # Insert aggregated generators and time series - network.import_components_from_dataframe(df, "Generator") - - for attr, data in df_t.items(): - if not data.empty: - network.import_series_from_dataframe( - data, "Generator", attr - ) - - return - import_gen_from_links(network) ac_buses = network.buses[network.buses.carrier == "AC"].index From 1d728d245fa46a9e8fe2232fcb3da465b89c9608 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 28 Mar 2023 15:14:20 +0200 Subject: [PATCH 42/58] delete not necessary legends for PowerToH2 plot --- etrago/tools/plot.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 25364b1c4..e5ea073ae 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2700,13 +2700,12 @@ def plot_grid( plt.setp(l2.get_title(), fontsize="9") - if not scaling_store_expansion: + if ((not scaling_store_expansion) & (bus_legend != "PowerToH2")): handles = [] if bus_legend == "Nodal production balance": positive = mpatches.Patch(color="green", label="generation") negative = mpatches.Patch(color="red", label="consumption") handles = [positive, negative] - elif legend_entries != "all": for i in legend_entries: patch = mpatches.Patch( From 71af64bab8f6eff324a30f874d63bd3df4a9551d Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Wed, 29 Mar 2023 08:44:51 +0200 Subject: [PATCH 43/58] Fix calculation DLR potential --- etrago/tools/plot.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index e5ea073ae..9245f0092 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2452,16 +2452,27 @@ def plot_grid( title = "Dynamic line rating" label = "MWh above nominal capacity" plot_background_grid(network, ax) - line_loading = network.lines_t.p0.mul( - 1 / (network.lines.s_nom_opt * network.lines.s_max_pu) - ) + # Extract branch_capacity_factors + bcf_hv = self.args["branch_capacity_factor"]["HV"] + bcf_ehv = self.args["branch_capacity_factor"]["eHV"] + # calc min capacity per line in the given period + network.lines.s_max_pu = network.lines_t.s_max_pu.min() + network.lines.s_max_pu[network.lines.s_max_pu < 0.7] = 0.5 + network.lines.s_max_pu[(network.lines.s_max_pu > 0.5) & + (network.lines.s_max_pu < 0.70)] = (bcf_hv + bcf_ehv)/2 + network.lines.s_max_pu[network.lines.s_max_pu >= 0.70] = 0.70 + line_loading = (network.lines_t.p0.mul( + 1 / (network.lines.s_nom_opt * network.lines.s_max_pu)).abs() + ) + # keep only the capacity allowed by dlr + line_loading = line_loading - 1 dlr_usage = ( - line_loading[line_loading.abs() > 1] + line_loading[line_loading > 0] .fillna(0) .mul(network.snapshot_weightings.generators, axis=0) - .abs() .sum() ) + dlr_usage = dlr_usage * network.lines.s_nom * network.lines.s_max_pu line_colors = dlr_usage if ext_width is not False: line_widths = 0.5 + (line_colors / ext_width) From 569303d9837dfd4a48746702c61597662d96bf57 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Wed, 29 Mar 2023 09:25:36 +0200 Subject: [PATCH 44/58] fix cropped figures when exporting to file --- etrago/tools/plot.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 9245f0092..37a5f13d8 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2649,7 +2649,7 @@ def plot_grid( geomap=False, boundaries=[-2.5, 16, 46.8, 58], ) - + l3 = None # legends for bus sizes and colors if bus_legend: handles = [] @@ -2769,8 +2769,11 @@ def plot_grid( plt.show() else: from matplotlib import pylab - - pylab.savefig(filename, dpi=300, bbox_inches="tight") + if l3 == None: + pylab.savefig(filename, dpi=300, bbox_inches='tight') + else: + pylab.savefig(filename, dpi=300, bbox_inches='tight', + bbox_extra_artists= [l3]) plt.close() From 1e2ac6182d645b246ffc2fde117198303e4b42e8 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Wed, 29 Mar 2023 15:51:06 +0200 Subject: [PATCH 45/58] add legends to the power2H2 plot --- etrago/tools/plot.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 37a5f13d8..0680c4eed 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2711,12 +2711,16 @@ def plot_grid( plt.setp(l2.get_title(), fontsize="9") - if ((not scaling_store_expansion) & (bus_legend != "PowerToH2")): + if not scaling_store_expansion: handles = [] if bus_legend == "Nodal production balance": positive = mpatches.Patch(color="green", label="generation") negative = mpatches.Patch(color="red", label="consumption") handles = [positive, negative] + + elif bus_legend == "PowerToH2": + pth = mpatches.Patch(color="cyan", label="PowerToH2") + handles = [pth] elif legend_entries != "all": for i in legend_entries: patch = mpatches.Patch( From 82eae3a16e9d755e962571dd0479cc30a13027e9 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Fri, 31 Mar 2023 11:44:32 +0200 Subject: [PATCH 46/58] make the parameter ext_width usable again --- etrago/tools/plot.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 0680c4eed..3d8cee30b 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1575,14 +1575,16 @@ def calc_dc_loading(network, timesteps): network.links.index == row["linked_to"] ].values[0], ) - - return ( + dc_load = ( mul_weighting(network, link_load) .loc[network.snapshots[timesteps]] .abs() .sum()[network.links.index] / p_nom_opt_max ).dropna() + dc_load.loc[network.links.carrier != "DC"] = 0 + + return dc_load def plotting_colors(network): @@ -2373,9 +2375,12 @@ def plot_grid( ].sum() line_colors = calc_ac_loading(network, timesteps).abs() / rep_snapshots link_colors = calc_dc_loading(network, timesteps).abs() / rep_snapshots - link_widths = network.links.carrier - link_widths = link_widths.apply(lambda x: 10 if x == "DC" else 0) - line_widths = 10 + if ext_width is not False: + link_widths = link_colors.apply(lambda x: 10 + (x/ext_width) if x != 0 else 0) + line_widths = 10 + (line_colors / ext_width) + else: + link_widths = link_colors.apply(lambda x: 10 if x != 0 else 0) + line_widths = 10 label = "line loading in p.u." plot_background_grid(network, ax) # Only active flow direction is displayed! @@ -2387,9 +2392,10 @@ def plot_grid( / network.lines.s_nom / rep_snapshots ).values - flow.iloc[flow.index.get_level_values("component") == "Link"] = ( - calc_dc_loading(network, timesteps) / rep_snapshots - ).values + + dc_loading = calc_dc_loading(network, timesteps) / rep_snapshots + dc_loading.index = pd.MultiIndex.from_tuples([("Link", name) for name in dc_loading.index], names = ["component", "name"]) + flow.loc["Link", :] = dc_loading flow = flow[ (flow.index.get_level_values("component") == "Line") @@ -2422,7 +2428,7 @@ def plot_grid( plot_background_grid(all_network, ax) if ext_width is not False: line_widths = 0.5 + (line_colors / ext_width) - link_widths = 0.5 + (line_colors / ext_width) + link_widths = link_colors.apply(lambda x: 0.5 + x / ext_width if x != 0 else 0) else: dc_link = network.links.index[network.links.carrier == "DC"] link_widths = pd.Series(0, index=network.links.index) @@ -2439,13 +2445,19 @@ def plot_grid( plot_background_grid(all_network, ax) if ext_width is not False: line_widths = 0.5 + (line_colors / ext_width) - link_widths = 0.5 + (link_colors / ext_width) + link_widths = link_colors.apply(lambda x: 0.5 + x / ext_width if x != 0 else 0) + else: + dc_link = network.links.index[network.links.carrier == "DC"] + link_widths = pd.Series(0, index=network.links.index) + link_widths.loc[dc_link] = 2 elif line_colors == "q_flow_max": title = "Maximum reactive power flows" label = "flow in pu" line_colors = abs( network.lines_t.q0.abs().max() / (network.lines.s_nom) ) + if ext_width is not False: + line_widths = 0.5 + (line_colors / ext_width) link_colors = pd.Series(data=0, index=network.links.index) plot_background_grid(network, ax) elif line_colors == "dlr": From 55bfbdddc941dfc9f04c8a1be73f9801b238e798 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Fri, 31 Mar 2023 11:57:47 +0200 Subject: [PATCH 47/58] Solve cropped legends when visualizing in IDE --- etrago/tools/plot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 3d8cee30b..15f2d39a9 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2782,6 +2782,7 @@ def plot_grid( if filename is None: if not isinstance(bus_sizes, (pd.Series, float)): logger.warning("Legend of bus sizes will change when zooming") + plt.tight_layout() plt.show() else: from matplotlib import pylab From 0e13a63ab2462a63aa196eedb82607f34b469a49 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Fri, 31 Mar 2023 13:21:01 +0200 Subject: [PATCH 48/58] use Black and Isort --- etrago/tools/plot.py | 158 +++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 72 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 15f2d39a9..800db821d 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -31,7 +31,6 @@ from pyproj import Proj, transform from pypsa.plot import draw_map_cartopy from shapely.geometry import LineString, Point -from etrago.tools.execute import import_gen_from_links import geopandas as gpd import matplotlib import matplotlib.patches as mpatches @@ -39,6 +38,8 @@ import pandas as pd import tilemapbase +from etrago.tools.execute import import_gen_from_links + cartopy_present = True try: import cartopy.crs as ccrs @@ -2277,63 +2278,63 @@ def plot_grid( ): """Function that plots etrago.network and results for lines and buses - Parameters - ---------- - line_colors : str - Set static line color or attribute to plot e.g. 'expansion_abs' - Current options: - 'line_loading': mean line loading in p.u. in selected timesteps - 'v_nom': nominal voltage of lines - 'expansion_abs': absolute network expansion in MVA - 'expansion_rel': network expansion in p.u. of existing capacity - 'q_flow_max': maximal reactive flows - 'dlr': energy above nominal capacity - 'grey': plot all lines and DC linkd grey colored - bus_sizes : float, optional - Size of buses. The default is 0.001. - bus_colors : str, optional - Set static bus color or attribute to plot. The default is 'grey'. - Current options: - 'nodal_production_balance': net producer/consumer in - selected timeteps - 'storage_expansion': storage expansion per bus and technology. - 'h2_battery_storage_expansion': storage expansion per bus and - technology for underground and overground H2 and batteries. - 'storage_distribution': installed storage units per bus - 'gen_dist': dispatch per carrier in selected timesteps - 'PowerToH2': location and sizes of electrolizers - 'flexibility_usage': use of DSM and BEV charger - timesteps : array, optional - Timesteps consideredd in time depended plots. The default - is range(2). - osm : bool or dict, e.g. {'x': [1,20], 'y': [47, 56], 'zoom' : 6} - If not False, osm is set as background - with the following settings as dict: - 'x': array of two floats, x axis boundaries (lat) - 'y': array of two floats, y axis boundaries (long) - 'zoom' : resolution of osm. The default is False. - boundaries: array - Set fixed boundaries of heatmap axis. The default is None. - filename: str or None - Save figure in this direction. The default is None. - disaggregated : bool, optional - Choose if disaggregated network is shown. The default is False. - ext_min: float - Choose minimum relative line extension shown in plot in p.u.. - ext_width: float or bool - Choose if line_width respects line extension. Turn off with - 'False' or set linear factor to decremise extension line_width. - The default is False. - legend_entries : list, optional - Set the legends for buses to be plotted. The default is 'all'. - scaling_store_expansion : dict, optional - Set scaling values to be used per technology for the plots - storage_expansion and h2_battery_storage_expansion. The default is - {"H2": 50, "heat": 0.1, "battery": 10} - - Returns - ------- - None. + Parameters + ---------- + line_colors : str + Set static line color or attribute to plot e.g. 'expansion_abs' + Current options: + 'line_loading': mean line loading in p.u. in selected timesteps + 'v_nom': nominal voltage of lines + 'expansion_abs': absolute network expansion in MVA + 'expansion_rel': network expansion in p.u. of existing capacity + 'q_flow_max': maximal reactive flows + 'dlr': energy above nominal capacity + 'grey': plot all lines and DC linkd grey colored + bus_sizes : float, optional + Size of buses. The default is 0.001. + bus_colors : str, optional + Set static bus color or attribute to plot. The default is 'grey'. + Current options: + 'nodal_production_balance': net producer/consumer in + selected timeteps + 'storage_expansion': storage expansion per bus and technology. + 'h2_battery_storage_expansion': storage expansion per bus and + technology for underground and overground H2 and batteries. + 'storage_distribution': installed storage units per bus + 'gen_dist': dispatch per carrier in selected timesteps + 'PowerToH2': location and sizes of electrolizers + 'flexibility_usage': use of DSM and BEV charger + timesteps : array, optional + Timesteps consideredd in time depended plots. The default + is range(2). + osm : bool or dict, e.g. {'x': [1,20], 'y': [47, 56], 'zoom' : 6} + If not False, osm is set as background + with the following settings as dict: + 'x': array of two floats, x axis boundaries (lat) + 'y': array of two floats, y axis boundaries (long) + 'zoom' : resolution of osm. The default is False. + boundaries: array + Set fixed boundaries of heatmap axis. The default is None. + filename: str or None + Save figure in this direction. The default is None. + disaggregated : bool, optional + Choose if disaggregated network is shown. The default is False. + ext_min: float + Choose minimum relative line extension shown in plot in p.u.. + ext_width: float or bool + Choose if line_width respects line extension. Turn off with + 'False' or set linear factor to decremise extension line_width. + The default is False. + legend_entries : list, optional + Set the legends for buses to be plotted. The default is 'all'. + scaling_store_expansion : dict, optional + Set scaling values to be used per technology for the plots + storage_expansion and h2_battery_storage_expansion. The default is + {"H2": 50, "heat": 0.1, "battery": 10} + + Returns + ------- + None. """ # Choose network or disaggregated_network @@ -2376,7 +2377,9 @@ def plot_grid( line_colors = calc_ac_loading(network, timesteps).abs() / rep_snapshots link_colors = calc_dc_loading(network, timesteps).abs() / rep_snapshots if ext_width is not False: - link_widths = link_colors.apply(lambda x: 10 + (x/ext_width) if x != 0 else 0) + link_widths = link_colors.apply( + lambda x: 10 + (x / ext_width) if x != 0 else 0 + ) line_widths = 10 + (line_colors / ext_width) else: link_widths = link_colors.apply(lambda x: 10 if x != 0 else 0) @@ -2394,7 +2397,10 @@ def plot_grid( ).values dc_loading = calc_dc_loading(network, timesteps) / rep_snapshots - dc_loading.index = pd.MultiIndex.from_tuples([("Link", name) for name in dc_loading.index], names = ["component", "name"]) + dc_loading.index = pd.MultiIndex.from_tuples( + [("Link", name) for name in dc_loading.index], + names=["component", "name"], + ) flow.loc["Link", :] = dc_loading flow = flow[ @@ -2428,7 +2434,9 @@ def plot_grid( plot_background_grid(all_network, ax) if ext_width is not False: line_widths = 0.5 + (line_colors / ext_width) - link_widths = link_colors.apply(lambda x: 0.5 + x / ext_width if x != 0 else 0) + link_widths = link_colors.apply( + lambda x: 0.5 + x / ext_width if x != 0 else 0 + ) else: dc_link = network.links.index[network.links.carrier == "DC"] link_widths = pd.Series(0, index=network.links.index) @@ -2445,7 +2453,9 @@ def plot_grid( plot_background_grid(all_network, ax) if ext_width is not False: line_widths = 0.5 + (line_colors / ext_width) - link_widths = link_colors.apply(lambda x: 0.5 + x / ext_width if x != 0 else 0) + link_widths = link_colors.apply( + lambda x: 0.5 + x / ext_width if x != 0 else 0 + ) else: dc_link = network.links.index[network.links.carrier == "DC"] link_widths = pd.Series(0, index=network.links.index) @@ -2470,12 +2480,13 @@ def plot_grid( # calc min capacity per line in the given period network.lines.s_max_pu = network.lines_t.s_max_pu.min() network.lines.s_max_pu[network.lines.s_max_pu < 0.7] = 0.5 - network.lines.s_max_pu[(network.lines.s_max_pu > 0.5) & - (network.lines.s_max_pu < 0.70)] = (bcf_hv + bcf_ehv)/2 + network.lines.s_max_pu[ + (network.lines.s_max_pu > 0.5) & (network.lines.s_max_pu < 0.70) + ] = (bcf_hv + bcf_ehv) / 2 network.lines.s_max_pu[network.lines.s_max_pu >= 0.70] = 0.70 - line_loading = (network.lines_t.p0.mul( - 1 / (network.lines.s_nom_opt * network.lines.s_max_pu)).abs() - ) + line_loading = network.lines_t.p0.mul( + 1 / (network.lines.s_nom_opt * network.lines.s_max_pu) + ).abs() # keep only the capacity allowed by dlr line_loading = line_loading - 1 dlr_usage = ( @@ -2695,7 +2706,8 @@ def plot_grid( labels.append( f""" {round(max_value/bus_scaling/scaling_store_expansion[i]/ - 1000, 0).astype(int)} {bus_unit} """ + i + 1000, 0).astype(int)} {bus_unit} """ + + i ) else: max_value = bus_sizes.max() @@ -2729,7 +2741,7 @@ def plot_grid( positive = mpatches.Patch(color="green", label="generation") negative = mpatches.Patch(color="red", label="consumption") handles = [positive, negative] - + elif bus_legend == "PowerToH2": pth = mpatches.Patch(color="cyan", label="PowerToH2") handles = [pth] @@ -2786,11 +2798,13 @@ def plot_grid( plt.show() else: from matplotlib import pylab + if l3 == None: - pylab.savefig(filename, dpi=300, bbox_inches='tight') + pylab.savefig(filename, dpi=300, bbox_inches="tight") else: - pylab.savefig(filename, dpi=300, bbox_inches='tight', - bbox_extra_artists= [l3]) + pylab.savefig( + filename, dpi=300, bbox_inches="tight", bbox_extra_artists=[l3] + ) plt.close() From 18e85bdb0204b6a94ad37bcc6ffab30f3565013e Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Fri, 31 Mar 2023 13:28:40 +0200 Subject: [PATCH 49/58] applying Flake8 --- etrago/tools/plot.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 800db821d..545774cd6 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -23,7 +23,6 @@ """ from math import sqrt import logging -import os from matplotlib import pyplot as plt from matplotlib.legend_handler import HandlerPatch @@ -49,9 +48,6 @@ logger = logging.getLogger(__name__) -if "READTHEDOCS" not in os.environ: - from geoalchemy2.shape import to_shape - __copyright__ = ( "Flensburg University of Applied Sciences, " "Europa-Universität Flensburg, " @@ -2799,7 +2795,7 @@ def plot_grid( else: from matplotlib import pylab - if l3 == None: + if l3 is None: pylab.savefig(filename, dpi=300, bbox_inches="tight") else: pylab.savefig( From 073700a38e9800d1dd93ffce50d38534c87b7f37 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Fri, 31 Mar 2023 15:50:20 +0200 Subject: [PATCH 50/58] import own functions checking READTHEDOCS --- etrago/tools/plot.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 545774cd6..c27f0cdaa 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -23,6 +23,7 @@ """ from math import sqrt import logging +import os from matplotlib import pyplot as plt from matplotlib.legend_handler import HandlerPatch @@ -37,7 +38,8 @@ import pandas as pd import tilemapbase -from etrago.tools.execute import import_gen_from_links +if "READTHEDOCS" not in os.environ: + from etrago.tools.execute import import_gen_from_links cartopy_present = True try: From 9c3fbc1dadd85e073424ce0f4f58f5276c41114a Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Wed, 5 Apr 2023 14:07:03 +0200 Subject: [PATCH 51/58] adjust dlr plot --- etrago/tools/plot.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index c27f0cdaa..274de4dfa 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2470,7 +2470,7 @@ def plot_grid( plot_background_grid(network, ax) elif line_colors == "dlr": title = "Dynamic line rating" - label = "MWh above nominal capacity" + label = "TWh above nominal capacity" plot_background_grid(network, ax) # Extract branch_capacity_factors bcf_hv = self.args["branch_capacity_factor"]["HV"] @@ -2493,10 +2493,13 @@ def plot_grid( .mul(network.snapshot_weightings.generators, axis=0) .sum() ) - dlr_usage = dlr_usage * network.lines.s_nom * network.lines.s_max_pu + dlr_usage = ( + dlr_usage * network.lines.s_nom * network.lines.s_max_pu / 1000000 + ) + dlr_usage = dlr_usage.round(decimals=0) line_colors = dlr_usage if ext_width is not False: - line_widths = 0.5 + (line_colors / ext_width) + line_widths = 0.2 + (line_colors / ext_width) link_colors = pd.Series(data=0, index=network.links.index) elif line_colors == "grey": From 791c76b0b1b58c1e790976447d4c1b73bd712874 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Mon, 17 Jul 2023 14:36:30 +0200 Subject: [PATCH 52/58] use p_opt - p_min in storage exp --- etrago/tools/plot.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 274de4dfa..2da438368 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -830,8 +830,10 @@ def calc_storage_expansion_per_bus( batteries = network.storage_units[ network.storage_units.carrier == "battery" ] + #breakpoint() battery_distribution = ( - network.storage_units.p_nom_opt[batteries.index] + (network.storage_units.p_nom_opt[batteries.index] - + network.storage_units.p_nom_min[batteries.index]) .groupby(network.storage_units.bus) .sum() .reindex(network.buses.index, fill_value=0.0) From 2a566a760ebe044135284f8856eb2e49e3361306 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Mon, 17 Jul 2023 16:00:37 +0200 Subject: [PATCH 53/58] dont color not expanded lines --- etrago/tools/plot.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 2da438368..4ce1883a4 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2432,18 +2432,21 @@ def plot_grid( network, method="abs", ext_min=ext_min ) plot_background_grid(all_network, ax) + if ext_width is not False: - line_widths = 0.5 + (line_colors / ext_width) + line_widths = (line_colors / ext_width) link_widths = link_colors.apply( - lambda x: 0.5 + x / ext_width if x != 0 else 0 + lambda x: x / ext_width if x != 0 else 0 ) else: dc_link = network.links.index[network.links.carrier == "DC"] link_widths = pd.Series(0, index=network.links.index) - link_widths.loc[dc_link] = 2 + link_widths.loc[dc_link] = 1.5 + line_widths = line_colors.apply(lambda x: 1.5 if x != 0 else 0) link_colors = link_colors.mul(1e-3) line_colors = line_colors.mul(1e-3) + elif line_colors == "expansion_rel": title = "Network expansion" label = "network expansion in %" From 6999e9cb8ea2d31423e4ec690ac44d1af8dc0f56 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Mon, 17 Jul 2023 17:16:16 +0200 Subject: [PATCH 54/58] use 1 decimal in color bar --- etrago/tools/plot.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 4ce1883a4..fa648ee0a 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2776,12 +2776,12 @@ def plot_grid( # Set fixed boundaries if selected in parameters if not boundaries: boundaries = [ - min(line_colors.min(), link_colors.min()), - max(line_colors.max(), link_colors.max()), + min(round(line_colors.min(),1), round(link_colors.min(),1)), + max(round(line_colors.max()), round(link_colors.max())), ] # Create ticks for legend - v = np.linspace(boundaries[0], boundaries[1], 101) + v = [round(x,1) for x in np.linspace(boundaries[0], boundaries[1], 101)] for l_collection in ll: l_collection.set_clim(boundaries[0], boundaries[1]) From 51d7ee01fcbd2125eee38edf2202d4d153b2f99f Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Mon, 25 Sep 2023 11:54:05 +0200 Subject: [PATCH 55/58] include snapshots in dlr plot and black --- etrago/tools/plot.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 3742e9538..75e4c09c1 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -25,6 +25,7 @@ import logging import os +from etrago.tools.execute import import_gen_from_links from matplotlib import pyplot as plt from matplotlib.legend_handler import HandlerPatch from matplotlib.patches import Circle, Ellipse @@ -855,10 +856,11 @@ def calc_storage_expansion_per_bus( batteries = network.storage_units[ network.storage_units.carrier == "battery" ] - #breakpoint() battery_distribution = ( - (network.storage_units.p_nom_opt[batteries.index] - - network.storage_units.p_nom_min[batteries.index]) + ( + network.storage_units.p_nom_opt[batteries.index] + - network.storage_units.p_nom_min[batteries.index] + ) .groupby(network.storage_units.bus) .sum() .reindex(network.buses.index, fill_value=0.0) @@ -1589,7 +1591,6 @@ def calc_dc_loading(network, timesteps): & (network.links.length == row["length"]) ] ).empty: - links_df = network.links.index[ (network.links.bus0 == row["bus1"]) & (network.links.bus1 == row["bus0"]) @@ -2483,7 +2484,7 @@ def plot_grid( plot_background_grid(all_network, ax) if ext_width is not False: - line_widths = (line_colors / ext_width) + line_widths = line_colors / ext_width link_widths = link_colors.apply( lambda x: x / ext_width if x != 0 else 0 ) @@ -2495,7 +2496,7 @@ def plot_grid( link_colors = link_colors.mul(1e-3) line_colors = line_colors.mul(1e-3) - + elif line_colors == "expansion_rel": title = "Network expansion" label = "network expansion in %" @@ -2539,6 +2540,7 @@ def plot_grid( line_loading = network.lines_t.p0.mul( 1 / (network.lines.s_nom_opt * network.lines.s_max_pu) ).abs() + line_loading = line_loading.iloc[timesteps, :] # keep only the capacity allowed by dlr line_loading = line_loading - 1 dlr_usage = ( @@ -2825,12 +2827,14 @@ def plot_grid( # Set fixed boundaries if selected in parameters if not boundaries: boundaries = [ - min(round(line_colors.min(),1), round(link_colors.min(),1)), + min(round(line_colors.min(), 1), round(link_colors.min(), 1)), max(round(line_colors.max()), round(link_colors.max())), ] # Create ticks for legend - v = [round(x,1) for x in np.linspace(boundaries[0], boundaries[1], 101)] + v = [ + round(x, 1) for x in np.linspace(boundaries[0], boundaries[1], 101) + ] for l_collection in ll: l_collection.set_clim(boundaries[0], boundaries[1]) From f33655dc33463a2f2445178ec29aaf2463d34fbd Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 26 Sep 2023 10:07:25 +0200 Subject: [PATCH 56/58] fix dlr plot --- etrago/tools/plot.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 75e4c09c1..089069969 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1673,7 +1673,7 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): Returns ------- - network_c : :class:`pypsa.Network + network : :class:`pypsa.Network Whole network including not extended lines extension_lines : pandas.Series AC-line expansion @@ -2335,7 +2335,7 @@ def plot_grid( * 'expansion_rel': network expansion in p.u. of existing capacity * 'q_flow_max': maximal reactive flows * 'dlr': energy above nominal capacity - * 'grey': plot all lines and DC linkd grey colored + * 'grey': plot all lines and DC links grey colored bus_sizes : float, optional Size of buses. The default is 0.001. @@ -2527,16 +2527,12 @@ def plot_grid( title = "Dynamic line rating" label = "TWh above nominal capacity" plot_background_grid(network, ax) - # Extract branch_capacity_factors - bcf_hv = self.args["branch_capacity_factor"]["HV"] - bcf_ehv = self.args["branch_capacity_factor"]["eHV"] - # calc min capacity per line in the given period + + # calc min capacity per line in the given period: Since lines with + # different original voltage level could be aggregated during the + # clustering, the security factors can be values in between the values + # provided in the args for branch_capacity_factor. network.lines.s_max_pu = network.lines_t.s_max_pu.min() - network.lines.s_max_pu[network.lines.s_max_pu < 0.7] = 0.5 - network.lines.s_max_pu[ - (network.lines.s_max_pu > 0.5) & (network.lines.s_max_pu < 0.70) - ] = (bcf_hv + bcf_ehv) / 2 - network.lines.s_max_pu[network.lines.s_max_pu >= 0.70] = 0.70 line_loading = network.lines_t.p0.mul( 1 / (network.lines.s_nom_opt * network.lines.s_max_pu) ).abs() From f6086973cef1a1fd444d24f28d73def775c11d99 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 26 Sep 2023 11:08:35 +0200 Subject: [PATCH 57/58] fix plots expansion_abs/rel --- etrago/tools/plot.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index 089069969..ba4de1133 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -1721,7 +1721,7 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): extension_links = pd.DataFrame( data=network_c.links, index=network_c.links.index ) - extension_links[extension_links.carrier != "DC"] = 0 + extension_links = ( 100 * (network_c.links.p_nom_opt - network_c.links.p_nom_min) @@ -1735,7 +1735,7 @@ def calc_network_expansion(network, method="abs", ext_min=0.1): extension_links = pd.DataFrame( data=network_c.links, index=network_c.links.index ) - extension_links[extension_links.carrier != "DC"] = 0 + extension_links = network_c.links.p_nom_opt - network_c.links.p_nom_min extension_lines = pd.Series( @@ -2513,6 +2513,7 @@ def plot_grid( dc_link = network.links.index[network.links.carrier == "DC"] link_widths = pd.Series(0, index=network.links.index) link_widths.loc[dc_link] = 2 + line_widths = line_colors.apply(lambda x: 1.5 if x != 0 else 0) elif line_colors == "q_flow_max": title = "Maximum reactive power flows" label = "flow in pu" From 783ea65badfff5cd337787c3f6ae0f72bf53a07d Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 26 Sep 2023 11:47:10 +0200 Subject: [PATCH 58/58] improve plot powertoH2 --- etrago/tools/plot.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/etrago/tools/plot.py b/etrago/tools/plot.py index ba4de1133..0ab5b8276 100644 --- a/etrago/tools/plot.py +++ b/etrago/tools/plot.py @@ -2680,6 +2680,8 @@ def plot_grid( .sum() .p_nom_opt ) + if len(bus_sizes) == 0: + print("There is no PowerToH2 to plot") bus_colors = coloring()["power_to_H2"] bus_legend = "PowerToH2" bus_unit = "TW" @@ -2727,6 +2729,7 @@ def plot_grid( boundaries=[-2.5, 16, 46.8, 58], ) l3 = None + # legends for bus sizes and colors if bus_legend: handles = [] @@ -2764,7 +2767,10 @@ def plot_grid( + i ) else: - max_value = bus_sizes.max() + if len(bus_sizes) > 0: + max_value = bus_sizes.max() + else: + max_value = 0 labels.append(f"{round(max_value / bus_scaling /1000, 0)} GWh ") handles.append( make_legend_circles_for(