From 5d696d25c158100ea25f80f1276b47409988e405 Mon Sep 17 00:00:00 2001 From: hzraja Date: Tue, 21 Mar 2023 15:21:19 +0100 Subject: [PATCH 01/33] Ground work for different sgen patches --- pandapower/plotting/collections.py | 11 +++-- pandapower/plotting/patch_makers.py | 62 +++++++++++++++++++---------- pandapower/plotting/simple_plot.py | 4 +- 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index b7300a8a7..8a14fdbe2 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -220,7 +220,7 @@ def _create_line2d_collection(coords, indices, infos=None, picker=False, **kwarg return lc -def _create_node_element_collection(node_coords, patch_maker, size=1., infos=None, +def _create_node_element_collection(node_coords, patch_maker,sgen_type = "", size=1., infos=None, repeat_infos=(1, 1), orientation=np.pi, picker=False, patch_facecolor="w", patch_edgecolor="k", line_color="k", **kwargs): @@ -275,9 +275,8 @@ def _create_node_element_collection(node_coords, patch_maker, size=1., infos=Non linewidths = kwargs.pop("linewidths", 2.) linewidths = kwargs.pop("linewidth", linewidths) linewidths = kwargs.pop("lw", linewidths) - lines, polys, popped_keywords = patch_maker( - node_coords, size, angles, patch_facecolor=patch_facecolor, patch_edgecolor=patch_edgecolor, + node_coords, size, angles, sgen_type=sgen_type, patch_facecolor=patch_facecolor, patch_edgecolor=patch_edgecolor, **kwargs) for kw in set(popped_keywords) & set(kwargs.keys()): kwargs.pop(kw) @@ -1019,7 +1018,7 @@ def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=np return gen_pc, gen_lc -def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation=np.pi, picker=False, +def create_sgen_collection(net, sgen_type, sgens=None, size=1., infofunc=None, orientation=np.pi, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower sgen. @@ -1051,9 +1050,9 @@ def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation= node_coords = net.bus_geodata.loc[net.sgen.loc[sgens, "bus"].values, ["x", "y"]].values color = kwargs.pop("color", "k") - + sgen_type = sgen_type[0] sgen_pc, sgen_lc = _create_node_element_collection( - node_coords, sgen_patches, size=size, infos=infos, orientation=orientation, + node_coords, sgen_patches, sgen_type, size=size, infos=infos, orientation=orientation, picker=picker, line_color=color, **kwargs) return sgen_pc, sgen_lc diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index e880e3b24..bb1f1f438 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -234,7 +234,7 @@ def gen_patches(node_coords, size, angles, **kwargs): return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} -def sgen_patches(node_coords, size, angles, **kwargs): +def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): """ Creation function of patches for static generators. @@ -261,25 +261,47 @@ def sgen_patches(node_coords, size, angles, **kwargs): facecolor = kwargs.get("patch_facecolor", "w") edgecolors = get_color_list(edgecolor, len(node_coords)) facecolors = get_color_list(facecolor, len(node_coords)) - for i, node_geo in enumerate(node_coords): - mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) - circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) - mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angles[i]) - mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angles[i]) - # dropped perpendicular foot of triangle1 - perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) - line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2.5 * r_triangle, 0]), angles[i]) - perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) - line_end2 = perp_foot2 + + _rotate_dim2(np.array([2.5 * r_triangle, 0]), angles[i]) - polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, - orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) - polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, - orientation=np.pi - angles[i], fc=facecolors[i], - ec=edgecolors[i])) - lines.append((node_geo, circ_edge)) - lines.append((perp_foot1, line_end1)) - lines.append((perp_foot2, line_end2)) + if sgen_type == "WT": + for i, node_geo in enumerate(node_coords): + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) + mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angles[i]) + mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angles[i]) + # dropped perpendicular foot of triangle1 + perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) + line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2.5 * r_triangle, 0]), angles[i]) + perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) + line_end2 = perp_foot2 + + _rotate_dim2(np.array([2.5 * r_triangle, 0]), angles[i]) + polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, + orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) + polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, + orientation=np.pi - angles[i], fc=facecolors[i], + ec=edgecolors[i])) + lines.append((node_geo, circ_edge)) + lines.append((perp_foot1, line_end1)) + lines.append((perp_foot2, line_end2)) + else: + for i, node_geo in enumerate(node_coords): + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) + mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angles[i]) + mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angles[i]) + # dropped perpendicular foot of triangle1 + perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) + line_end1 = perp_foot1 + + _rotate_dim2(np.array([-55.5 * r_triangle, 0]), angles[i]) + perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) + line_end2 = perp_foot2 + + _rotate_dim2(np.array([55.5 * r_triangle, 0]), angles[i]) + polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, + orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) + polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, + orientation=np.pi - angles[i], fc=facecolors[i], + ec=edgecolors[i])) + lines.append((node_geo, circ_edge)) + lines.append((perp_foot1, line_end1)) + lines.append((perp_foot2, line_end2)) + return lines, polys, {"offset", "r_triangle", "patch_edgecolor", "patch_facecolor"} diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index 118313f77..cf2a8031b 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -172,9 +172,9 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g net, size=switch_size, distance_to_bus=switch_distance, use_line_geodata=not use_bus_geodata, zorder=12, color=switch_color) collections.append(sc) - if plot_sgens and len(net.sgen): - sgc = create_sgen_collection(net, size=sgen_size, orientation=0) + sgen_type = net.sgen.type + sgc = create_sgen_collection(net, sgen_type, size=sgen_size, orientation=0) collections.append(sgc) if plot_gens and len(net.gen): gc = create_gen_collection(net, size=gen_size) From 193483fd599a0d11f61d00474c67fa28cc1eda95 Mon Sep 17 00:00:00 2001 From: hzraja Date: Tue, 28 Mar 2023 18:10:42 +0200 Subject: [PATCH 02/33] Updated patch_maker with sgen WT (line based single blade) --- pandapower/plotting/patch_makers.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index bb1f1f438..de3715830 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -257,11 +257,25 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): polys, lines = list(), list() offset = kwargs.get("offset", 2 * size) r_triangle = kwargs.get("r_triangles", size * 0.4) + midcirc_size = size * 0.1 edgecolor = kwargs.get("patch_edgecolor", "w") facecolor = kwargs.get("patch_facecolor", "w") edgecolors = get_color_list(edgecolor, len(node_coords)) facecolors = get_color_list(facecolor, len(node_coords)) + + if sgen_type == "WT": + for i, node_geo in enumerate(node_coords): + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) + mid_midcirc = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) + midcirc_bottomedge = node_geo + _rotate_dim2(np.array([0, offset + size - midcirc_size]), angles[i]) + polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + + polys.append(Circle(mid_midcirc, midcirc_size, fc=facecolors[i], ec=edgecolors[i])) + lines.append((midcirc_bottomedge, circ_edge)) + + elif sgen_type == "WTT": for i, node_geo in enumerate(node_coords): mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) @@ -269,9 +283,9 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angles[i]) # dropped perpendicular foot of triangle1 perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) - line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2.5 * r_triangle, 0]), angles[i]) + line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2 * r_triangle, 0]), angles[i]) perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) - line_end2 = perp_foot2 + + _rotate_dim2(np.array([2.5 * r_triangle, 0]), angles[i]) + line_end2 = perp_foot2 + + _rotate_dim2(np.array([55.5 * r_triangle, 0]), angles[i]) polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) @@ -288,20 +302,21 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angles[i]) mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angles[i]) # dropped perpendicular foot of triangle1 - perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) - line_end1 = perp_foot1 + + _rotate_dim2(np.array([-55.5 * r_triangle, 0]), angles[i]) + perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) + line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2 * r_triangle, 0]), angles[i]) perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) line_end2 = perp_foot2 + + _rotate_dim2(np.array([55.5 * r_triangle, 0]), angles[i]) polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, - orientation=np.pi - angles[i], fc=facecolors[i], + orientation=np.pi - angles[i], fc=facecolors[i], ec=edgecolors[i])) lines.append((node_geo, circ_edge)) lines.append((perp_foot1, line_end1)) lines.append((perp_foot2, line_end2)) + return lines, polys, {"offset", "r_triangle", "patch_edgecolor", "patch_facecolor"} From 411a3b7770d10eab44232dee6890db2d71096d79 Mon Sep 17 00:00:00 2001 From: hzraja Date: Thu, 30 Mar 2023 20:17:52 +0200 Subject: [PATCH 03/33] Updated patch_maker for sgen type WT (3 blade design) --- pandapower/plotting/patch_makers.py | 38 +++++++++-------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index de3715830..b180a61cf 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -264,38 +264,24 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): facecolors = get_color_list(facecolor, len(node_coords)) - if sgen_type == "WT": + if sgen_type == "WT": #Special patch for sgen_type "Wind Turbine" for i, node_geo in enumerate(node_coords): mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) mid_midcirc = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) midcirc_bottomedge = node_geo + _rotate_dim2(np.array([0, offset + size - midcirc_size]), angles[i]) + #Blades end coordinates + blade1 = midcirc_bottomedge + 0.0225 + blade2 = [midcirc_bottomedge[0]-0.028, midcirc_bottomedge[1]+0.01] + blade3 = [circ_edge[0]+0.01, circ_edge[1]+0.002] polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - - polys.append(Circle(mid_midcirc, midcirc_size, fc=facecolors[i], ec=edgecolors[i])) - lines.append((midcirc_bottomedge, circ_edge)) - - elif sgen_type == "WTT": - for i, node_geo in enumerate(node_coords): - mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) - circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) - mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angles[i]) - mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angles[i]) - # dropped perpendicular foot of triangle1 - perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) - line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2 * r_triangle, 0]), angles[i]) - perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) - line_end2 = perp_foot2 + + _rotate_dim2(np.array([55.5 * r_triangle, 0]), angles[i]) - polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, - orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) - polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, - orientation=np.pi - angles[i], fc=facecolors[i], - ec=edgecolors[i])) + polys.append(Circle(mid_midcirc, midcirc_size, fc="k", ec=edgecolors[i])) lines.append((node_geo, circ_edge)) - lines.append((perp_foot1, line_end1)) - lines.append((perp_foot2, line_end2)) - else: + lines.append((mid_midcirc, blade1)) + lines.append((mid_midcirc, blade2)) + lines.append((mid_midcirc, blade3)) + + else: for i, node_geo in enumerate(node_coords): mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) @@ -305,7 +291,7 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2 * r_triangle, 0]), angles[i]) perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) - line_end2 = perp_foot2 + + _rotate_dim2(np.array([55.5 * r_triangle, 0]), angles[i]) + line_end2 = perp_foot2 + + _rotate_dim2(np.array([2 * r_triangle, 0]), angles[i]) polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) From f303f9928e48c4d41dacfd31864e034ad0f5d115 Mon Sep 17 00:00:00 2001 From: hzraja Date: Sun, 23 Apr 2023 11:51:48 +0200 Subject: [PATCH 04/33] Added support for PV patch & reworked WT patch --- pandapower/plotting/patch_makers.py | 104 +++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 19 deletions(-) diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index b180a61cf..ca9fa80da 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -5,7 +5,10 @@ import sys import numpy as np try: - from matplotlib.patches import RegularPolygon, Arc, Circle, Rectangle, Ellipse + from matplotlib.patches import RegularPolygon, Arc, Circle, Rectangle, Ellipse, Wedge, PathPatch, Polygon + import matplotlib.path as mpath + import math + MATPLOTLIB_INSTALLED = True except ImportError: MATPLOTLIB_INSTALLED = False @@ -257,52 +260,115 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): polys, lines = list(), list() offset = kwargs.get("offset", 2 * size) r_triangle = kwargs.get("r_triangles", size * 0.4) - midcirc_size = size * 0.1 + midcirc_size = size * 0.15 edgecolor = kwargs.get("patch_edgecolor", "w") facecolor = kwargs.get("patch_facecolor", "w") edgecolors = get_color_list(edgecolor, len(node_coords)) facecolors = get_color_list(facecolor, len(node_coords)) - + Path = mpath.Path if sgen_type == "WT": #Special patch for sgen_type "Wind Turbine" for i, node_geo in enumerate(node_coords): mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) + circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2* size]), angles[i]) mid_midcirc = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) - midcirc_bottomedge = node_geo + _rotate_dim2(np.array([0, offset + size - midcirc_size]), angles[i]) - #Blades end coordinates - blade1 = midcirc_bottomedge + 0.0225 - blade2 = [midcirc_bottomedge[0]-0.028, midcirc_bottomedge[1]+0.01] - blade3 = [circ_edge[0]+0.01, circ_edge[1]+0.002] + # midcirc_bottomedge = node_geo + _rotate_dim2(np.array([0, offset + size - midcirc_size]), angles[i]) + # #Blades end coordinates + # blade1 = circ_topedge + # blade2 = [midcirc_bottomedge[0]-0.027, midcirc_bottomedge[1]-0.01] + # blade3 = [circ_edge[0]+0.026, circ_edge[1]+0.015] + # polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + # lines.append((node_geo, circ_edge)) + # #Line based + # #lines.append((mid_midcirc, blade1)) + # #lines.append((mid_midcirc, blade2)) + # #lines.append((mid_midcirc, blade3)) + + #path based + codes, verts = zip(*[ + (Path.MOVETO, mid_midcirc), + (Path.LINETO, circ_topedge), + (Path.LINETO, [circ_topedge[0] - 0.003, circ_topedge[1] - 0.003]), + (Path.LINETO, [mid_midcirc[0] - 0.007, mid_midcirc[1] + 0.007]), # Blade1 + # (Path.MOVETO, mid_midcirc), + # (Path.LINETO, [midcirc_bottomedge[0] - 0.027, midcirc_bottomedge[1] - 0.01]), + # (Path.LINETO, [midcirc_bottomedge[0] - 0.023, midcirc_bottomedge[1] - 0.013]), + # (Path.LINETO, [mid_midcirc[0] - 0.0055, mid_midcirc[1] - 0.01]), # Blade2 + # (Path.MOVETO, mid_midcirc), + # (Path.LINETO, [midcirc_bottomedge[0] + 0.024, midcirc_bottomedge[1] - 0.015]), + # (Path.LINETO, [midcirc_bottomedge[0] + 0.025, midcirc_bottomedge[1] - 0.010]), + # (Path.LINETO, [mid_midcirc[0] + 0.010, mid_midcirc[1] + 0.0025]), # Blade3 + + (Path.CLOSEPOLY, [0.018, -0.11])]) + polys.append(PathPatch(mpath.Path(verts, codes),fc= "k", ec="none")) polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - polys.append(Circle(mid_midcirc, midcirc_size, fc="k", ec=edgecolors[i])) lines.append((node_geo, circ_edge)) - lines.append((mid_midcirc, blade1)) - lines.append((mid_midcirc, blade2)) - lines.append((mid_midcirc, blade3)) - else: + + #chatgpt + for i in range(3): + angle = i * 2 * math.pi / 3 + + rotated_verts = [] + for vertex in verts: + # Calculate the vector from the center of the hub to the vertex + x_diff = vertex[0] - mid_midcirc[0] + y_diff = vertex[1] - mid_midcirc[1] + + # Rotate the vector by the desired angle + rotated_x = x_diff * math.cos(angle) - y_diff * math.sin(angle) + rotated_y = x_diff * math.sin(angle) + y_diff * math.cos(angle) + + # Calculate the coordinates of the rotated vertex + rotated_vertex = [mid_midcirc[0] + rotated_x, mid_midcirc[1] + rotated_y] + + rotated_verts.append(rotated_vertex) + + rotated_patch = PathPatch(mpath.Path(rotated_verts, codes), fc="k", ec="none") + polys.append(rotated_patch) + + polys.append(Circle(mid_midcirc, midcirc_size, fc="k", ec=edgecolors[i])) #Center hub + + elif sgen_type == "PV": #Special patch for sgen_type "Wind Turbine" + for i, node_geo in enumerate(node_coords): + mid_rect = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) + rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] + pv_patch = Rectangle((rect_lbottom), 0.05, 0.1, ec="k", fc="none") + polys.append(pv_patch) + lines.append((node_geo, mid_rect)) + triangle_base = 0.05 + triangle_height = 0.05 + triangle_points = [ + (mid_rect[0] - triangle_base / 2, mid_rect[1] + 0.1), + (mid_rect[0] + triangle_base / 2, mid_rect[1] + 0.1), + (mid_rect[0] , mid_rect[1] + triangle_height), + ] + triangle_patch = Polygon(triangle_points, ec="k", fc="none") + polys.append(triangle_patch) + + + + else: for i, node_geo in enumerate(node_coords): mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angles[i]) mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angles[i]) # dropped perpendicular foot of triangle1 - perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) - line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2 * r_triangle, 0]), angles[i]) + perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) + line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2.5 * r_triangle, 0]), angles[i]) perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) - line_end2 = perp_foot2 + + _rotate_dim2(np.array([2 * r_triangle, 0]), angles[i]) + line_end2 = perp_foot2 + + _rotate_dim2(np.array([2.5 * r_triangle, 0]), angles[i]) polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, - orientation=np.pi - angles[i], fc=facecolors[i], + orientation=np.pi - angles[i], fc=facecolors[i], ec=edgecolors[i])) lines.append((node_geo, circ_edge)) lines.append((perp_foot1, line_end1)) lines.append((perp_foot2, line_end2)) - - return lines, polys, {"offset", "r_triangle", "patch_edgecolor", "patch_facecolor"} From e6320bc17df17974989d1e2a1d96b8da059996f8 Mon Sep 17 00:00:00 2001 From: hzraja Date: Mon, 24 Apr 2023 15:39:48 +0200 Subject: [PATCH 05/33] Added support for PV patch orientation --- pandapower/plotting/patch_makers.py | 66 ++++++++++++++++------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index ca9fa80da..704e593de 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -8,6 +8,8 @@ from matplotlib.patches import RegularPolygon, Arc, Circle, Rectangle, Ellipse, Wedge, PathPatch, Polygon import matplotlib.path as mpath import math + import matplotlib.pyplot as plt + import matplotlib.transforms as transforms MATPLOTLIB_INSTALLED = True except ImportError: @@ -273,40 +275,17 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2* size]), angles[i]) mid_midcirc = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) - # midcirc_bottomedge = node_geo + _rotate_dim2(np.array([0, offset + size - midcirc_size]), angles[i]) - # #Blades end coordinates - # blade1 = circ_topedge - # blade2 = [midcirc_bottomedge[0]-0.027, midcirc_bottomedge[1]-0.01] - # blade3 = [circ_edge[0]+0.026, circ_edge[1]+0.015] - # polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - # lines.append((node_geo, circ_edge)) - # #Line based - # #lines.append((mid_midcirc, blade1)) - # #lines.append((mid_midcirc, blade2)) - # #lines.append((mid_midcirc, blade3)) - - #path based + codes, verts = zip(*[ (Path.MOVETO, mid_midcirc), (Path.LINETO, circ_topedge), (Path.LINETO, [circ_topedge[0] - 0.003, circ_topedge[1] - 0.003]), (Path.LINETO, [mid_midcirc[0] - 0.007, mid_midcirc[1] + 0.007]), # Blade1 - # (Path.MOVETO, mid_midcirc), - # (Path.LINETO, [midcirc_bottomedge[0] - 0.027, midcirc_bottomedge[1] - 0.01]), - # (Path.LINETO, [midcirc_bottomedge[0] - 0.023, midcirc_bottomedge[1] - 0.013]), - # (Path.LINETO, [mid_midcirc[0] - 0.0055, mid_midcirc[1] - 0.01]), # Blade2 - # (Path.MOVETO, mid_midcirc), - # (Path.LINETO, [midcirc_bottomedge[0] + 0.024, midcirc_bottomedge[1] - 0.015]), - # (Path.LINETO, [midcirc_bottomedge[0] + 0.025, midcirc_bottomedge[1] - 0.010]), - # (Path.LINETO, [mid_midcirc[0] + 0.010, mid_midcirc[1] + 0.0025]), # Blade3 - (Path.CLOSEPOLY, [0.018, -0.11])]) polys.append(PathPatch(mpath.Path(verts, codes),fc= "k", ec="none")) polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) lines.append((node_geo, circ_edge)) - - #chatgpt for i in range(3): angle = i * 2 * math.pi / 3 @@ -326,6 +305,7 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): rotated_verts.append(rotated_vertex) rotated_patch = PathPatch(mpath.Path(rotated_verts, codes), fc="k", ec="none") + polys.append(rotated_patch) polys.append(Circle(mid_midcirc, midcirc_size, fc="k", ec=edgecolors[i])) #Center hub @@ -334,21 +314,49 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): for i, node_geo in enumerate(node_coords): mid_rect = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] - pv_patch = Rectangle((rect_lbottom), 0.05, 0.1, ec="k", fc="none") + pv_patch = Rectangle((rect_lbottom), 0.05, 0.1,angle=-angles[i]*(180/np.pi),rotation_point=(mid_rect[0],mid_rect[1]),ec="k", fc="none") polys.append(pv_patch) lines.append((node_geo, mid_rect)) triangle_base = 0.05 triangle_height = 0.05 triangle_points = [ - (mid_rect[0] - triangle_base / 2, mid_rect[1] + 0.1), - (mid_rect[0] + triangle_base / 2, mid_rect[1] + 0.1), - (mid_rect[0] , mid_rect[1] + triangle_height), + (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 0.1]), angles[i])), + (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 0.1]), angles[i])), + (mid_rect + _rotate_dim2(np.array([0, + triangle_height]), angles[i])), ] - triangle_patch = Polygon(triangle_points, ec="k", fc="none") + triangle_patch = Polygon(triangle_points,ec="k", fc="none") polys.append(triangle_patch) + elif sgen_type == "HEP": + + for i, node_geo in enumerate(node_coords): + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) + + circ_topedge = mid_circ + _rotate_dim2(np.array([0, size]), angles[i]) + hep_patch = Rectangle([circ_topedge[0]-0.005,circ_topedge[1]-0], 0.01, 0.02, ec="k", fc="k") + polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + polys.append(hep_patch) + for i in range(3): + angle = i * 2 * math.pi / 3 + rotated_verts = [] + for vertex in hep_patch.get_verts(): + # Calculate the vector from the center of the hub to the vertex + x_diff = vertex[0] - circ_topedge[0] + y_diff = vertex[1] - circ_topedge[1] + + # Rotate the vector by the desired angle + rotated_x = x_diff * math.cos(angle) - y_diff * math.sin(angle) + rotated_y = x_diff * math.sin(angle) + y_diff * math.cos(angle) + + # Calculate the coordinates of the rotated vertex + rotated_vertex = [circ_topedge[0] + rotated_x, circ_topedge[1] + rotated_y] + + rotated_verts.append(rotated_vertex) + + rotated_patch = Rectangle(rotated_vertex, 0.01, 0.02, ec="k",fc="k") + polys.append(rotated_patch) else: for i, node_geo in enumerate(node_coords): mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) From f98102348fd5efa77dd17a60d053b69c2c0643ae Mon Sep 17 00:00:00 2001 From: hzraja Date: Tue, 25 Apr 2023 11:58:22 +0200 Subject: [PATCH 06/33] Added support for WT patch orientation --- pandapower/plotting/patch_makers.py | 70 ++++++++++++++--------------- pandapower/plotting/simple_plot.py | 2 +- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 704e593de..45088e31d 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -279,9 +279,9 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): codes, verts = zip(*[ (Path.MOVETO, mid_midcirc), (Path.LINETO, circ_topedge), - (Path.LINETO, [circ_topedge[0] - 0.003, circ_topedge[1] - 0.003]), - (Path.LINETO, [mid_midcirc[0] - 0.007, mid_midcirc[1] + 0.007]), # Blade1 - (Path.CLOSEPOLY, [0.018, -0.11])]) + (Path.LINETO, (circ_topedge + _rotate_dim2(np.array([- 0.003, - 0.003]), angles[i])),), + (Path.LINETO, (mid_midcirc + _rotate_dim2(np.array([- 0.007, + 0.007]), angles[i])),), # Blade1 + (Path.CLOSEPOLY, mid_midcirc)]) polys.append(PathPatch(mpath.Path(verts, codes),fc= "k", ec="none")) polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) lines.append((node_geo, circ_edge)) @@ -310,7 +310,7 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): polys.append(Circle(mid_midcirc, midcirc_size, fc="k", ec=edgecolors[i])) #Center hub - elif sgen_type == "PV": #Special patch for sgen_type "Wind Turbine" + elif sgen_type == "PV": #Special patch for sgen_type "Photo-voltaic" for i, node_geo in enumerate(node_coords): mid_rect = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] @@ -327,37 +327,37 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): triangle_patch = Polygon(triangle_points,ec="k", fc="none") polys.append(triangle_patch) - elif sgen_type == "HEP": - - for i, node_geo in enumerate(node_coords): - mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) - - circ_topedge = mid_circ + _rotate_dim2(np.array([0, size]), angles[i]) - hep_patch = Rectangle([circ_topedge[0]-0.005,circ_topedge[1]-0], 0.01, 0.02, ec="k", fc="k") - polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - polys.append(hep_patch) - - for i in range(3): - angle = i * 2 * math.pi / 3 - - rotated_verts = [] - for vertex in hep_patch.get_verts(): - # Calculate the vector from the center of the hub to the vertex - x_diff = vertex[0] - circ_topedge[0] - y_diff = vertex[1] - circ_topedge[1] - - # Rotate the vector by the desired angle - rotated_x = x_diff * math.cos(angle) - y_diff * math.sin(angle) - rotated_y = x_diff * math.sin(angle) + y_diff * math.cos(angle) - - # Calculate the coordinates of the rotated vertex - rotated_vertex = [circ_topedge[0] + rotated_x, circ_topedge[1] + rotated_y] - - rotated_verts.append(rotated_vertex) - - rotated_patch = Rectangle(rotated_vertex, 0.01, 0.02, ec="k",fc="k") - polys.append(rotated_patch) - else: + # elif sgen_type == "HEP": + # + # for i, node_geo in enumerate(node_coords): + # mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) + # + # circ_topedge = mid_circ + _rotate_dim2(np.array([0, size]), angles[i]) + # hep_patch = Rectangle([circ_topedge[0]-0.005,circ_topedge[1]-0], 0.01, 0.02, ec="k", fc="k") + # polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + # polys.append(hep_patch) + # + # for i in range(3): + # angle = i * 2 * math.pi / 3 + # + # rotated_verts = [] + # for vertex in hep_patch.get_verts(): + # # Calculate the vector from the center of the hub to the vertex + # x_diff = vertex[0] - circ_topedge[0] + # y_diff = vertex[1] - circ_topedge[1] + # + # # Rotate the vector by the desired angle + # rotated_x = x_diff * math.cos(angle) - y_diff * math.sin(angle) + # rotated_y = x_diff * math.sin(angle) + y_diff * math.cos(angle) + # + # # Calculate the coordinates of the rotated vertex + # rotated_vertex = [circ_topedge[0] + rotated_x, circ_topedge[1] + rotated_y] + # + # rotated_verts.append(rotated_vertex) + # + # rotated_patch = Rectangle(rotated_vertex, 0.01, 0.02, ec="k",fc="k") + # polys.append(rotated_patch) + else: #Generic patch for i, node_geo in enumerate(node_coords): mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index cf2a8031b..058887b44 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -174,7 +174,7 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g collections.append(sc) if plot_sgens and len(net.sgen): sgen_type = net.sgen.type - sgc = create_sgen_collection(net, sgen_type, size=sgen_size, orientation=0) + sgc = create_sgen_collection(net, sgen_type, size=sgen_size, orientation=4) collections.append(sgc) if plot_gens and len(net.gen): gc = create_gen_collection(net, size=gen_size) From 9de40f0c30dfffe13be7fa35df6cc686b422532c Mon Sep 17 00:00:00 2001 From: hzraja Date: Tue, 25 Apr 2023 14:03:32 +0200 Subject: [PATCH 07/33] Removed unwanted imports --- pandapower/plotting/patch_makers.py | 5 ++--- pandapower/plotting/simple_plot.py | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 45088e31d..0faf4d1e2 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -8,8 +8,7 @@ from matplotlib.patches import RegularPolygon, Arc, Circle, Rectangle, Ellipse, Wedge, PathPatch, Polygon import matplotlib.path as mpath import math - import matplotlib.pyplot as plt - import matplotlib.transforms as transforms + MATPLOTLIB_INSTALLED = True except ImportError: @@ -318,7 +317,7 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): polys.append(pv_patch) lines.append((node_geo, mid_rect)) triangle_base = 0.05 - triangle_height = 0.05 + triangle_height = 0.06 triangle_points = [ (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 0.1]), angles[i])), (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 0.1]), angles[i])), diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index 058887b44..cf2a8031b 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -174,7 +174,7 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g collections.append(sc) if plot_sgens and len(net.sgen): sgen_type = net.sgen.type - sgc = create_sgen_collection(net, sgen_type, size=sgen_size, orientation=4) + sgc = create_sgen_collection(net, sgen_type, size=sgen_size, orientation=0) collections.append(sgc) if plot_gens and len(net.gen): gc = create_gen_collection(net, size=gen_size) From 717a8d2ba0aff5b911cab5526aae05dd18a6e3ff Mon Sep 17 00:00:00 2001 From: hzraja Date: Wed, 26 Apr 2023 14:30:54 +0200 Subject: [PATCH 08/33] Fixed a bug where only 1 type of sgen patch was plotted on all nodes --- pandapower/plotting/collections.py | 9 ++- pandapower/plotting/patch_makers.py | 90 ++++++++++------------------- 2 files changed, 33 insertions(+), 66 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index 59f127df7..b8430afa3 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -222,7 +222,7 @@ def _create_line2d_collection(coords, indices, infos=None, picker=False, **kwarg return lc -def _create_node_element_collection(node_coords, patch_maker,sgen_type = "", size=1., infos=None, +def _create_node_element_collection(node_coords, patch_maker,sgen_type , size=1., infos=None, repeat_infos=(1, 1), orientation=np.pi, picker=False, patch_facecolor="w", patch_edgecolor="k", line_color="k", **kwargs): @@ -1069,9 +1069,8 @@ def create_sgen_collection(net, sgen_type, sgens=None, size=1., infofunc=None, o node_coords = net.bus_geodata.loc[net.sgen.loc[sgens, "bus"].values, ["x", "y"]].values color = kwargs.pop("color", "k") - sgen_type = sgen_type[0] sgen_pc, sgen_lc = _create_node_element_collection( - node_coords, sgen_patches, sgen_type, size=size, infos=infos, orientation=orientation, + node_coords, sgen_patches, sgen_type = sgen_type, size=size, infos=infos, orientation=orientation, picker=picker, line_color=color, **kwargs) return sgen_pc, sgen_lc @@ -1153,11 +1152,11 @@ def create_ext_grid_collection(net, size=1., infofunc=None, orientation=0, picke infos = [infofunc(ext_grid_idx) for ext_grid_idx in ext_grids] if infofunc is not None else [] node_coords = net.bus_geodata.loc[ext_grid_buses, ["x", "y"]].values - + sgen_type = net.sgen.type color = kwargs.pop("color", "k") ext_grid_pc, ext_grid_lc = _create_node_element_collection( - node_coords, ext_grid_patches, size=size, infos=infos, orientation=orientation, + node_coords, ext_grid_patches,sgen_type, size=size, infos=infos, orientation=orientation, picker=picker, hatch='XXX', line_color=color, **kwargs) return ext_grid_pc, ext_grid_lc diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 0faf4d1e2..76470f157 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -268,8 +268,8 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): facecolors = get_color_list(facecolor, len(node_coords)) Path = mpath.Path - if sgen_type == "WT": #Special patch for sgen_type "Wind Turbine" - for i, node_geo in enumerate(node_coords): + for i, node_geo in enumerate(node_coords): + if sgen_type[i] == "WT": #Special patch for sgen_type "Wind Turbine" mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2* size]), angles[i]) @@ -285,9 +285,8 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) lines.append((node_geo, circ_edge)) - for i in range(3): - angle = i * 2 * math.pi / 3 - + for j in range(3): + angle = j * 2 * math.pi / 3 rotated_verts = [] for vertex in verts: # Calculate the vector from the center of the hub to the vertex @@ -309,8 +308,8 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): polys.append(Circle(mid_midcirc, midcirc_size, fc="k", ec=edgecolors[i])) #Center hub - elif sgen_type == "PV": #Special patch for sgen_type "Photo-voltaic" - for i, node_geo in enumerate(node_coords): + elif sgen_type[i] == "PV": #Special patch for sgen_type "Photo-voltaic" + mid_rect = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] pv_patch = Rectangle((rect_lbottom), 0.05, 0.1,angle=-angles[i]*(180/np.pi),rotation_point=(mid_rect[0],mid_rect[1]),ec="k", fc="none") @@ -319,63 +318,32 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): triangle_base = 0.05 triangle_height = 0.06 triangle_points = [ - (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 0.1]), angles[i])), - (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 0.1]), angles[i])), - (mid_rect + _rotate_dim2(np.array([0, + triangle_height]), angles[i])), - ] + (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 0.1]), angles[i])), + (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 0.1]), angles[i])), + (mid_rect + _rotate_dim2(np.array([0, + triangle_height]), angles[i])), + ] triangle_patch = Polygon(triangle_points,ec="k", fc="none") polys.append(triangle_patch) + else: + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) + mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angles[i]) + mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angles[i]) + # dropped perpendicular foot of triangle1 + perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) + line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2.5 * r_triangle, 0]), angles[i]) + perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) + line_end2 = perp_foot2 + + _rotate_dim2(np.array([2.5 * r_triangle, 0]), angles[i]) + polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, + orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) + polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, + orientation=np.pi - angles[i], fc=facecolors[i], + ec=edgecolors[i])) + lines.append((node_geo, circ_edge)) + lines.append((perp_foot1, line_end1)) + lines.append((perp_foot2, line_end2)) - # elif sgen_type == "HEP": - # - # for i, node_geo in enumerate(node_coords): - # mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) - # - # circ_topedge = mid_circ + _rotate_dim2(np.array([0, size]), angles[i]) - # hep_patch = Rectangle([circ_topedge[0]-0.005,circ_topedge[1]-0], 0.01, 0.02, ec="k", fc="k") - # polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - # polys.append(hep_patch) - # - # for i in range(3): - # angle = i * 2 * math.pi / 3 - # - # rotated_verts = [] - # for vertex in hep_patch.get_verts(): - # # Calculate the vector from the center of the hub to the vertex - # x_diff = vertex[0] - circ_topedge[0] - # y_diff = vertex[1] - circ_topedge[1] - # - # # Rotate the vector by the desired angle - # rotated_x = x_diff * math.cos(angle) - y_diff * math.sin(angle) - # rotated_y = x_diff * math.sin(angle) + y_diff * math.cos(angle) - # - # # Calculate the coordinates of the rotated vertex - # rotated_vertex = [circ_topedge[0] + rotated_x, circ_topedge[1] + rotated_y] - # - # rotated_verts.append(rotated_vertex) - # - # rotated_patch = Rectangle(rotated_vertex, 0.01, 0.02, ec="k",fc="k") - # polys.append(rotated_patch) - else: #Generic patch - for i, node_geo in enumerate(node_coords): - mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) - circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) - mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angles[i]) - mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angles[i]) - # dropped perpendicular foot of triangle1 - perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) - line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2.5 * r_triangle, 0]), angles[i]) - perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) - line_end2 = perp_foot2 + + _rotate_dim2(np.array([2.5 * r_triangle, 0]), angles[i]) - polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, - orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) - polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, - orientation=np.pi - angles[i], fc=facecolors[i], - ec=edgecolors[i])) - lines.append((node_geo, circ_edge)) - lines.append((perp_foot1, line_end1)) - lines.append((perp_foot2, line_end2)) return lines, polys, {"offset", "r_triangle", "patch_edgecolor", "patch_facecolor"} From 77a4d7180982af1e7e41594e260efa54e91c333c Mon Sep 17 00:00:00 2001 From: hzraja Date: Mon, 15 May 2023 11:53:42 +0200 Subject: [PATCH 09/33] mutiple patches on same node partial fix --- pandapower/plotting/collections.py | 6 ++- pandapower/plotting/patch_makers.py | 51 +++++++++++++++++-------- pandapower/plotting/plotting_toolbox.py | 9 +++++ pandapower/plotting/simple_plot.py | 2 +- 4 files changed, 50 insertions(+), 18 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index b8430afa3..cf6555523 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -959,7 +959,7 @@ def create_busbar_collection(net, buses=None, infofunc=None, cmap=None, norm=Non return lc -def create_load_collection(net, loads=None, size=1., infofunc=None, orientation=np.pi, picker=False, +def create_load_collection(net,sgen_type, loads=None, size=1., infofunc=None, orientation=np.pi, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower loads. @@ -986,6 +986,8 @@ def create_load_collection(net, loads=None, size=1., infofunc=None, orientation= **load_lc** - line collection """ + # sgens = get_index_array(sgens, net.sgen.index) + loads = get_index_array(loads, net.load.index) infos = [infofunc(i) for i in range(len(loads))] if infofunc is not None else [] node_coords = net.bus_geodata.loc[net.load.loc[loads, "bus"].values, ["x", "y"]].values @@ -993,7 +995,7 @@ def create_load_collection(net, loads=None, size=1., infofunc=None, orientation= color = kwargs.pop("color", "k") load_pc, load_lc = _create_node_element_collection( - node_coords, load_patches, size=size, infos=infos, orientation=orientation, + node_coords, load_patches,sgen_type=sgen_type, size=size, infos=infos, orientation=orientation, picker=picker, line_color=color, **kwargs) return load_pc, load_lc diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 76470f157..252d0f7ed 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -308,22 +308,42 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): polys.append(Circle(mid_midcirc, midcirc_size, fc="k", ec=edgecolors[i])) #Center hub + elif sgen_type[i] == "PV": #Special patch for sgen_type "Photo-voltaic" - mid_rect = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) - rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] - pv_patch = Rectangle((rect_lbottom), 0.05, 0.1,angle=-angles[i]*(180/np.pi),rotation_point=(mid_rect[0],mid_rect[1]),ec="k", fc="none") - polys.append(pv_patch) - lines.append((node_geo, mid_rect)) - triangle_base = 0.05 - triangle_height = 0.06 - triangle_points = [ - (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 0.1]), angles[i])), - (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 0.1]), angles[i])), - (mid_rect + _rotate_dim2(np.array([0, + triangle_height]), angles[i])), - ] - triangle_patch = Polygon(triangle_points,ec="k", fc="none") - polys.append(triangle_patch) + if node_geo[0] not in node_coords[i+1:, 0]: + angle = angles[i] + mid_rect = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] + pv_patch = Rectangle((rect_lbottom), 0.05, 0.1, angle=-angle * (180 / np.pi), + rotation_point=(mid_rect[0], mid_rect[1]), ec="k", fc="none") + polys.append(pv_patch) + lines.append((node_geo, mid_rect)) + triangle_base = 0.05 + triangle_height = 0.06 + triangle_points = [ + (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 0.1]), angle)), + (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 0.1]), angle)), + (mid_rect + _rotate_dim2(np.array([0, + triangle_height]), angle)), + ] + triangle_patch = Polygon(triangle_points, ec="k", fc="none") + polys.append(triangle_patch) + else: + angle = angles[i] + np.pi # 180° offset + mid_rect = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] + pv_patch = Rectangle((rect_lbottom), 0.05, 0.1,angle=-angle*(180/np.pi),rotation_point=(mid_rect[0],mid_rect[1]),ec="k", fc="none") + polys.append(pv_patch) + lines.append((node_geo, mid_rect)) + triangle_base = 0.05 + triangle_height = 0.06 + triangle_points = [ + (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 0.1]), angle)), + (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 0.1]), angle)), + (mid_rect + _rotate_dim2(np.array([0, + triangle_height]), angle)), + ] + triangle_patch = Polygon(triangle_points,ec="k", fc="none") + polys.append(triangle_patch) else: mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) @@ -344,6 +364,7 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): lines.append((perp_foot1, line_end1)) lines.append((perp_foot2, line_end2)) + # multi_check(node_coords) return lines, polys, {"offset", "r_triangle", "patch_edgecolor", "patch_facecolor"} @@ -470,4 +491,4 @@ def trafo_patches(coords, size, **kwargs): lp2 = (0.5 - off / d - size_this / d) * (p1 - p2) + p2 lines.append([p1, lp1]) lines.append([p2, lp2]) - return lines, circles, {"patch_edgecolor", "patch_facecolor"} + return lines, circles, {"patch_edgecolor", "patch_facecolor"} \ No newline at end of file diff --git a/pandapower/plotting/plotting_toolbox.py b/pandapower/plotting/plotting_toolbox.py index 4fa31e790..f344add7b 100644 --- a/pandapower/plotting/plotting_toolbox.py +++ b/pandapower/plotting/plotting_toolbox.py @@ -262,3 +262,12 @@ def position_on_busbar(net, bus, busbar_coords): intersection = busbar_coords[-1] return intersection + +# def multi_check(node_coords): +# seen = [] +# for i, arr in enumerate(node_coords): +# if arr[:, 0] in seen: +# return print("Repeating entry detected at index 0 of nd array", i) +# break +# else: +# seen.append(arr[:, 0]) diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index cf2a8031b..9eff4861c 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -180,7 +180,7 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g gc = create_gen_collection(net, size=gen_size) collections.append(gc) if plot_loads and len(net.load): - lc = create_load_collection(net, size=load_size) + lc = create_load_collection(net, sgen_type, size=load_size) collections.append(lc) if len(net.switch): From 70294d959bde490e720c98c64aa379457370daf6 Mon Sep 17 00:00:00 2001 From: hzraja Date: Mon, 22 May 2023 14:56:17 +0200 Subject: [PATCH 10/33] multiple patches hardcoded positions --- pandapower/plotting/collections.py | 8 +- pandapower/plotting/patch_makers.py | 141 ++++++++++++++-------------- pandapower/plotting/simple_plot.py | 8 +- 3 files changed, 77 insertions(+), 80 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index cf6555523..d07a56182 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -222,7 +222,7 @@ def _create_line2d_collection(coords, indices, infos=None, picker=False, **kwarg return lc -def _create_node_element_collection(node_coords, patch_maker,sgen_type , size=1., infos=None, +def _create_node_element_collection(node_coords, patch_maker,sgen_type = None , size=1., infos=None, repeat_infos=(1, 1), orientation=np.pi, picker=False, patch_facecolor="w", patch_edgecolor="k", line_color="k", **kwargs): @@ -959,7 +959,7 @@ def create_busbar_collection(net, buses=None, infofunc=None, cmap=None, norm=Non return lc -def create_load_collection(net,sgen_type, loads=None, size=1., infofunc=None, orientation=np.pi, picker=False, +def create_load_collection(net, loads=None, size=1., infofunc=None, orientation=None, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower loads. @@ -995,12 +995,12 @@ def create_load_collection(net,sgen_type, loads=None, size=1., infofunc=None, or color = kwargs.pop("color", "k") load_pc, load_lc = _create_node_element_collection( - node_coords, load_patches,sgen_type=sgen_type, size=size, infos=infos, orientation=orientation, + node_coords, load_patches, size=size, infos=infos, orientation=orientation, picker=picker, line_color=color, **kwargs) return load_pc, load_lc -def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=np.pi, picker=False, +def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=None, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower gens. diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 252d0f7ed..69a86112b 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -6,7 +6,11 @@ import numpy as np try: from matplotlib.patches import RegularPolygon, Arc, Circle, Rectangle, Ellipse, Wedge, PathPatch, Polygon + from matplotlib import text import matplotlib.path as mpath + import matplotlib.transforms as mtransforms + + import math @@ -190,14 +194,15 @@ def load_patches(node_coords, size, angles, **kwargs): facecolors = get_color_list(facecolor, len(node_coords)) polys, lines = list(), list() for i, node_geo in enumerate(node_coords): - p2 = node_geo + _rotate_dim2(np.array([0, offset + size]), all_angles[i]) - p3 = node_geo + _rotate_dim2(np.array([0, offset + size / 2]), all_angles[i]) - polys.append(RegularPolygon(p2, numVertices=3, radius=size, orientation=-all_angles[i], + p2 = node_geo + _rotate_dim2(np.array([0, offset + size]), all_angles[i] - np.pi ) + p3 = node_geo + _rotate_dim2(np.array([0, offset + size / 2]), all_angles[i]- np.pi) + polys.append(RegularPolygon(p2, numVertices=3, radius=size, orientation=-all_angles[i] - np.pi, fc=facecolors[i], ec=edgecolors[i])) lines.append((node_geo, p3)) return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} + def gen_patches(node_coords, size, angles, **kwargs): """ Creation function of patches for generators. @@ -226,7 +231,7 @@ def gen_patches(node_coords, size, angles, **kwargs): edgecolors = get_color_list(edgecolor, len(node_coords)) facecolors = get_color_list(facecolor, len(node_coords)) for i, node_geo in enumerate(node_coords): - p2 = node_geo + _rotate_dim2(np.array([0, size + offset]), all_angles[i]) + p2 = node_geo + _rotate_dim2(np.array([0, size + offset]), all_angles[i] - 2*np.pi/3) polys.append(Circle(p2, size, fc=facecolors[i], ec=edgecolors[i])) polys.append( Arc(p2 + np.array([-size / 6.2, -size / 2.6]), size / 2, size, theta1=65, theta2=120, @@ -236,9 +241,10 @@ def gen_patches(node_coords, size, angles, **kwargs): ec=edgecolors[i])) lines.append((node_geo, p2 + _rotate_dim2(np.array([0, size]), -all_angles[i]))) return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} + gen_printed = True -def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): +def sgen_patches(node_coords, size, angles,sgen_type,load_printed= None, **kwargs): """ Creation function of patches for static generators. @@ -268,23 +274,27 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): facecolors = get_color_list(facecolor, len(node_coords)) Path = mpath.Path + + for i, node_geo in enumerate(node_coords): - if sgen_type[i] == "WT": #Special patch for sgen_type "Wind Turbine" - mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) - circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) - circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2* size]), angles[i]) - mid_midcirc = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) + if sgen_type[i] == "WT": # Special patch for sgen_type "Wind Turbine" + angle = angles[i] - np.pi / 4 + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) + circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2 * size]), angle) + mid_midcirc = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) codes, verts = zip(*[ (Path.MOVETO, mid_midcirc), (Path.LINETO, circ_topedge), - (Path.LINETO, (circ_topedge + _rotate_dim2(np.array([- 0.003, - 0.003]), angles[i])),), - (Path.LINETO, (mid_midcirc + _rotate_dim2(np.array([- 0.007, + 0.007]), angles[i])),), # Blade1 + (Path.LINETO, (circ_topedge + _rotate_dim2(np.array([- 0.003, - 0.003]), angle)),), + (Path.LINETO, (mid_midcirc + _rotate_dim2(np.array([- 0.007, + 0.007]), angle)),), # Blade1 (Path.CLOSEPOLY, mid_midcirc)]) - polys.append(PathPatch(mpath.Path(verts, codes),fc= "k", ec="none")) + polys.append(PathPatch(mpath.Path(verts, codes), fc="k", ec="none")) polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) lines.append((node_geo, circ_edge)) + for j in range(3): angle = j * 2 * math.pi / 3 rotated_verts = [] @@ -306,65 +316,52 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): polys.append(rotated_patch) - polys.append(Circle(mid_midcirc, midcirc_size, fc="k", ec=edgecolors[i])) #Center hub - - - elif sgen_type[i] == "PV": #Special patch for sgen_type "Photo-voltaic" - - if node_geo[0] not in node_coords[i+1:, 0]: - angle = angles[i] - mid_rect = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) - rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] - pv_patch = Rectangle((rect_lbottom), 0.05, 0.1, angle=-angle * (180 / np.pi), - rotation_point=(mid_rect[0], mid_rect[1]), ec="k", fc="none") - polys.append(pv_patch) - lines.append((node_geo, mid_rect)) - triangle_base = 0.05 - triangle_height = 0.06 - triangle_points = [ - (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 0.1]), angle)), - (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 0.1]), angle)), - (mid_rect + _rotate_dim2(np.array([0, + triangle_height]), angle)), - ] - triangle_patch = Polygon(triangle_points, ec="k", fc="none") - polys.append(triangle_patch) - else: - angle = angles[i] + np.pi # 180° offset - mid_rect = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) - rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] - pv_patch = Rectangle((rect_lbottom), 0.05, 0.1,angle=-angle*(180/np.pi),rotation_point=(mid_rect[0],mid_rect[1]),ec="k", fc="none") - polys.append(pv_patch) - lines.append((node_geo, mid_rect)) - triangle_base = 0.05 - triangle_height = 0.06 - triangle_points = [ - (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 0.1]), angle)), - (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 0.1]), angle)), - (mid_rect + _rotate_dim2(np.array([0, + triangle_height]), angle)), - ] - triangle_patch = Polygon(triangle_points,ec="k", fc="none") - polys.append(triangle_patch) - else: - mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) - circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) - mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angles[i]) - mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angles[i]) - # dropped perpendicular foot of triangle1 - perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) - line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2.5 * r_triangle, 0]), angles[i]) - perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) - line_end2 = perp_foot2 + + _rotate_dim2(np.array([2.5 * r_triangle, 0]), angles[i]) - polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, - orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) - polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, - orientation=np.pi - angles[i], fc=facecolors[i], - ec=edgecolors[i])) - lines.append((node_geo, circ_edge)) - lines.append((perp_foot1, line_end1)) - lines.append((perp_foot2, line_end2)) - - # multi_check(node_coords) + polys.append(Circle(mid_midcirc, midcirc_size, fc="k", ec=edgecolors[i])) # Center hub + + center_point = mid_midcirc # Define the center point of the wind turbine patch + rotation_angle = math.pi / 4 # Define the angle of rotation + + + elif sgen_type[i] == "PV": # Special patch for sgen_type "Photo-voltaic" + angle = angles[i] + np.pi / 4 + + + mid_rect = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] + pv_patch = Rectangle((rect_lbottom), 0.05, 0.1, angle=-angle * (180 / np.pi), + rotation_point=(mid_rect[0], mid_rect[1]), ec="k", fc="none") + polys.append(pv_patch) + lines.append((node_geo, mid_rect)) + triangle_base = 0.05 + triangle_height = 0.06 + triangle_points = [ + (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 0.1]), angle)), + (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 0.1]), angle)), + (mid_rect + _rotate_dim2(np.array([0, + triangle_height]), angle)), + ] + triangle_patch = Polygon(triangle_points, ec="k", fc="none") + polys.append(triangle_patch) + else: # Generic Patch + angle = angles[i] + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) + mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angle) + mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angle) + # dropped perpendicular foot of triangle1 + perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angle) + line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2.5 * r_triangle, 0]), angle) + perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angle) + line_end2 = perp_foot2 + + _rotate_dim2(np.array([2.5 * r_triangle, 0]), angle) + polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, + orientation=-angle, fc=facecolors[i], ec=edgecolors[i])) + polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, + orientation=np.pi - angle, fc=facecolors[i], + ec=edgecolors[i])) + lines.append((node_geo, circ_edge)) + lines.append((perp_foot1, line_end1)) + lines.append((perp_foot2, line_end2)) + return lines, polys, {"offset", "r_triangle", "patch_edgecolor", "patch_facecolor"} diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index 9eff4861c..a76c66e6a 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -26,7 +26,7 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_grid_size=1.0, - trafo_size=1.0, plot_loads=False, plot_gens=False, plot_sgens=False, load_size=1.0, gen_size=1.0, sgen_size=1.0, + trafo_size=1.0, plot_loads=False, plot_gens=False, plot_sgens=False, orientation = None, load_size=1.0, gen_size=1.0, sgen_size=1.0, switch_size=2.0, switch_distance=1.0, plot_line_switches=False, scale_size=True, bus_color='b', line_color='grey', dcline_color='c', trafo_color='k', ext_grid_color='y', switch_color='k', library='igraph', show_plot=True, ax=None): @@ -174,13 +174,13 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g collections.append(sc) if plot_sgens and len(net.sgen): sgen_type = net.sgen.type - sgc = create_sgen_collection(net, sgen_type, size=sgen_size, orientation=0) + sgc = create_sgen_collection(net, sgen_type, size=sgen_size, orientation=orientation) collections.append(sgc) if plot_gens and len(net.gen): - gc = create_gen_collection(net, size=gen_size) + gc = create_gen_collection(net, size=gen_size,orientation=orientation) collections.append(gc) if plot_loads and len(net.load): - lc = create_load_collection(net, sgen_type, size=load_size) + lc = create_load_collection(net, size=load_size,orientation=orientation) collections.append(lc) if len(net.switch): From 67ac4ac5cf4758f390f4d02a95881cfe75ebcb6d Mon Sep 17 00:00:00 2001 From: hzraja Date: Fri, 26 May 2023 16:32:48 +0200 Subject: [PATCH 11/33] unique patch count implementation --- pandapower/plotting/collections.py | 2 +- pandapower/plotting/patch_makers.py | 8 ++--- pandapower/plotting/simple_plot.py | 45 ++++++++++++++++++++--------- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index d07a56182..558e04595 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -1039,7 +1039,7 @@ def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=No return gen_pc, gen_lc -def create_sgen_collection(net, sgen_type, sgens=None, size=1., infofunc=None, orientation=np.pi, picker=False, +def create_sgen_collection(net, sgen_type, sgens=None, size=1., infofunc=None, orientation=None, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower sgen. diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 69a86112b..c28ca5e00 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -10,10 +10,6 @@ import matplotlib.path as mpath import matplotlib.transforms as mtransforms - - import math - - MATPLOTLIB_INSTALLED = True except ImportError: MATPLOTLIB_INSTALLED = False @@ -28,7 +24,6 @@ logger = logging.getLogger(__name__) - def node_patches(node_coords, size, patch_type, colors=None, **kwargs): """ Creates node patches from coordinates translating the patch type into patches. @@ -199,6 +194,7 @@ def load_patches(node_coords, size, angles, **kwargs): polys.append(RegularPolygon(p2, numVertices=3, radius=size, orientation=-all_angles[i] - np.pi, fc=facecolors[i], ec=edgecolors[i])) lines.append((node_geo, p3)) + return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} @@ -244,7 +240,7 @@ def gen_patches(node_coords, size, angles, **kwargs): gen_printed = True -def sgen_patches(node_coords, size, angles,sgen_type,load_printed= None, **kwargs): +def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): """ Creation function of patches for static generators. diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index a76c66e6a..a9260522c 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -16,6 +16,8 @@ create_line_switch_collection, draw_collections, create_bus_bus_switch_collection, create_ext_grid_collection, create_sgen_collection, \ create_gen_collection, create_load_collection, create_dcline_collection from pandapower.plotting.generic_geodata import create_generic_coordinates +from pandapower import get_connected_elements_dict +import pandapower as pp try: import pandaplan.core.pplog as logging @@ -96,6 +98,7 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g OUTPUT: **ax** - axes of figure """ + # don't hide lines if switches are plotted if plot_line_switches: respect_switches = False @@ -167,25 +170,39 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g color=trafo_color) collections.append(tc) + #TODO Calculate patch angles based on number of elements here + # get_connected_elements_dict + # unique() + + if plot_line_switches and len(net.switch): sc = create_line_switch_collection( net, size=switch_size, distance_to_bus=switch_distance, use_line_geodata=not use_bus_geodata, zorder=12, color=switch_color) collections.append(sc) - if plot_sgens and len(net.sgen): - sgen_type = net.sgen.type - sgc = create_sgen_collection(net, sgen_type, size=sgen_size, orientation=orientation) - collections.append(sgc) - if plot_gens and len(net.gen): - gc = create_gen_collection(net, size=gen_size,orientation=orientation) - collections.append(gc) - if plot_loads and len(net.load): - lc = create_load_collection(net, size=load_size,orientation=orientation) - collections.append(lc) - - if len(net.switch): - bsc = create_bus_bus_switch_collection(net, size=switch_size) - collections.append(bsc) + + total_patches = len(get_connected_elements_dict(net, element_types=["sgen", "gen", "load"], buses=1)) + len( + net.sgen.type.unique()) + patch_count_unique = [] + for i in range(len(net.bus)): + + if plot_sgens and len(net.sgen): + patch_count_unique.insert(i, (len(net.sgen[net.sgen.bus == i].type.unique()))) + sgen_type = net.sgen.type + sgc = create_sgen_collection(net, sgen_type, size=sgen_size, orientation=orientation) + collections.append(sgc) + if plot_gens and len(net.gen): + patch_count_unique[i] += (len(pp.get_connected_elements_dict(net, element_types=["gen"], buses=i))) + gc = create_gen_collection(net, size=gen_size,orientation=orientation) + collections.append(gc) + if plot_loads and len(net.load): + patch_count_unique[i] += (len(pp.get_connected_elements_dict(net, element_types=["load"], buses=i))) + lc = create_load_collection(net, size=load_size,orientation=orientation) + collections.append(lc) + + if len(net.switch): + bsc = create_bus_bus_switch_collection(net, size=switch_size) + collections.append(bsc) ax = draw_collections(collections, ax=ax) if show_plot: From 71c5ffd93d14368e434d6f84e4974b059b01e233 Mon Sep 17 00:00:00 2001 From: hzraja Date: Tue, 30 May 2023 10:36:55 +0200 Subject: [PATCH 12/33] resolved arguments --- pandapower/plotting/simple_plot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index a9260522c..2307fd6bc 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -183,7 +183,7 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g total_patches = len(get_connected_elements_dict(net, element_types=["sgen", "gen", "load"], buses=1)) + len( net.sgen.type.unique()) - patch_count_unique = [] + patch_count_unique = [] #Unique patch on each node for i in range(len(net.bus)): if plot_sgens and len(net.sgen): From 7675b095369d423d69f7456f6cbb927d5c97e81d Mon Sep 17 00:00:00 2001 From: hzraja Date: Tue, 13 Jun 2023 12:50:26 +0200 Subject: [PATCH 13/33] multiple patches v0.9 --- pandapower/plotting/collections.py | 16 +++---- pandapower/plotting/patch_makers.py | 70 +++++++++++++++++++++++------ pandapower/plotting/simple_plot.py | 60 ++++++++++++++++++------- 3 files changed, 109 insertions(+), 37 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index 558e04595..7215dadd4 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -222,7 +222,7 @@ def _create_line2d_collection(coords, indices, infos=None, picker=False, **kwarg return lc -def _create_node_element_collection(node_coords, patch_maker,sgen_type = None , size=1., infos=None, +def _create_node_element_collection(node_coords, patch_maker,sgen_type = None , size=1., angle_list = None, infos=None, repeat_infos=(1, 1), orientation=np.pi, picker=False, patch_facecolor="w", patch_edgecolor="k", line_color="k", **kwargs): @@ -278,7 +278,7 @@ def _create_node_element_collection(node_coords, patch_maker,sgen_type = None , linewidths = kwargs.pop("linewidth", linewidths) linewidths = kwargs.pop("lw", linewidths) lines, polys, popped_keywords = patch_maker( - node_coords, size, angles, sgen_type=sgen_type, patch_facecolor=patch_facecolor, patch_edgecolor=patch_edgecolor, + node_coords, size, angles, sgen_type=sgen_type, angle_list=angle_list, patch_facecolor=patch_facecolor, patch_edgecolor=patch_edgecolor, **kwargs) for kw in set(popped_keywords) & set(kwargs.keys()): kwargs.pop(kw) @@ -959,7 +959,7 @@ def create_busbar_collection(net, buses=None, infofunc=None, cmap=None, norm=Non return lc -def create_load_collection(net, loads=None, size=1., infofunc=None, orientation=None, picker=False, +def create_load_collection(net, loads=None, size=1.,load_angle_list = None, patch_count = None, infofunc=None, orientation=None, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower loads. @@ -995,12 +995,12 @@ def create_load_collection(net, loads=None, size=1., infofunc=None, orientation= color = kwargs.pop("color", "k") load_pc, load_lc = _create_node_element_collection( - node_coords, load_patches, size=size, infos=infos, orientation=orientation, + node_coords, load_patches, size=size,angle_list=load_angle_list, infos=infos, orientation=orientation, picker=picker, line_color=color, **kwargs) return load_pc, load_lc -def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=None, picker=False, +def create_gen_collection(net, gens=None, size=1.,gen_angle_list=None,patch_count=None, infofunc=None, orientation=None, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower gens. @@ -1034,12 +1034,12 @@ def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=No color = kwargs.pop("color", "k") gen_pc, gen_lc = _create_node_element_collection( - node_coords, gen_patches, size=size, infos=infos, orientation=orientation, + node_coords, gen_patches, size=size,angle_list=gen_angle_list, infos=infos, orientation=orientation, picker=picker, line_color=color, **kwargs) return gen_pc, gen_lc -def create_sgen_collection(net, sgen_type, sgens=None, size=1., infofunc=None, orientation=None, picker=False, +def create_sgen_collection(net, sgen_type, sgens=None, size=1.,sgen_angle_list = None, infofunc=None, orientation=None, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower sgen. @@ -1072,7 +1072,7 @@ def create_sgen_collection(net, sgen_type, sgens=None, size=1., infofunc=None, o color = kwargs.pop("color", "k") sgen_pc, sgen_lc = _create_node_element_collection( - node_coords, sgen_patches, sgen_type = sgen_type, size=size, infos=infos, orientation=orientation, + node_coords, sgen_patches, sgen_type = sgen_type, size=size,angle_list=sgen_angle_list, infos=infos, orientation=orientation, picker=picker, line_color=color, **kwargs) return sgen_pc, sgen_lc diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index c28ca5e00..1bd7a0801 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -9,6 +9,7 @@ from matplotlib import text import matplotlib.path as mpath import matplotlib.transforms as mtransforms + import math MATPLOTLIB_INSTALLED = True except ImportError: @@ -161,7 +162,8 @@ def polygon_patches(node_coords, radius, num_edges, color=None, **kwargs): return patches -def load_patches(node_coords, size, angles, **kwargs): + +def load_patches(node_coords, size, angles,angle_list, **kwargs): """ Creation function of patches for loads. @@ -188,10 +190,23 @@ def load_patches(node_coords, size, angles, **kwargs): edgecolors = get_color_list(edgecolor, len(node_coords)) facecolors = get_color_list(facecolor, len(node_coords)) polys, lines = list(), list() + + + flatten_list = [item for sublist in angle_list for item in sublist] + + angle_list = flatten_list + last_entry = angle_list.pop() + angle_list.insert(0, last_entry) + for i, node_geo in enumerate(node_coords): - p2 = node_geo + _rotate_dim2(np.array([0, offset + size]), all_angles[i] - np.pi ) - p3 = node_geo + _rotate_dim2(np.array([0, offset + size / 2]), all_angles[i]- np.pi) - polys.append(RegularPolygon(p2, numVertices=3, radius=size, orientation=-all_angles[i] - np.pi, + try: + angle = angle_list[i] #Exception for index out of range in case of multiple elements of same type + except IndexError: + print("Index out of range!") + angle = angle_list[- 1] + p2 = node_geo + _rotate_dim2(np.array([0, offset + size]), angle ) + p3 = node_geo + _rotate_dim2(np.array([0, offset + size / 2]), angle) + polys.append(RegularPolygon(p2, numVertices=3, radius=size, orientation=angle, fc=facecolors[i], ec=edgecolors[i])) lines.append((node_geo, p3)) @@ -199,7 +214,7 @@ def load_patches(node_coords, size, angles, **kwargs): -def gen_patches(node_coords, size, angles, **kwargs): +def gen_patches(node_coords, size, angles, angle_list, **kwargs): """ Creation function of patches for generators. @@ -226,8 +241,21 @@ def gen_patches(node_coords, size, angles, **kwargs): facecolor = kwargs.get("patch_facecolor", (1, 0, 0, 0)) edgecolors = get_color_list(edgecolor, len(node_coords)) facecolors = get_color_list(facecolor, len(node_coords)) + + flatten_list = [item for sublist in angle_list for item in sublist] + + angle_list = flatten_list + last_entry = angle_list.pop() + angle_list.insert(0, last_entry) + + for i, node_geo in enumerate(node_coords): - p2 = node_geo + _rotate_dim2(np.array([0, size + offset]), all_angles[i] - 2*np.pi/3) + try: + angle = angle_list[i] #Exception for index out of range in case of multiple elements of same type + except IndexError: + print("Index out of range!") + angle = angle_list[- 1] + p2 = node_geo + _rotate_dim2(np.array([0, size + offset]), angle) polys.append(Circle(p2, size, fc=facecolors[i], ec=edgecolors[i])) polys.append( Arc(p2 + np.array([-size / 6.2, -size / 2.6]), size / 2, size, theta1=65, theta2=120, @@ -235,12 +263,12 @@ def gen_patches(node_coords, size, angles, **kwargs): polys.append( Arc(p2 + np.array([size / 6.2, size / 2.6]), size / 2, size, theta1=245, theta2=300, ec=edgecolors[i])) - lines.append((node_geo, p2 + _rotate_dim2(np.array([0, size]), -all_angles[i]))) + lines.append((node_geo, p2 + _rotate_dim2(np.array([0, size]), -angle))) return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} gen_printed = True -def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): +def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): """ Creation function of patches for static generators. @@ -270,11 +298,20 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): facecolors = get_color_list(facecolor, len(node_coords)) Path = mpath.Path + flatten_list = [item for sublist in angle_list for item in sublist] + + angle_list = flatten_list + last_entry = angle_list.pop() + angle_list.insert(0, last_entry) for i, node_geo in enumerate(node_coords): if sgen_type[i] == "WT": # Special patch for sgen_type "Wind Turbine" - angle = angles[i] - np.pi / 4 + try: #Exception for index out of range in case of multiple elements of same type + angle = angle_list[i] + except IndexError: + print("Index out of range!") + angle = angle_list[- 1] mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2 * size]), angle) @@ -319,9 +356,11 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): elif sgen_type[i] == "PV": # Special patch for sgen_type "Photo-voltaic" - angle = angles[i] + np.pi / 4 - - + try: + angle = angle_list[i] #Exception for index out of range in case of multiple elements of same type + except IndexError: + print("Index out of range!") + angle = angle_list[- 1] mid_rect = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] pv_patch = Rectangle((rect_lbottom), 0.05, 0.1, angle=-angle * (180 / np.pi), @@ -338,7 +377,12 @@ def sgen_patches(node_coords, size, angles,sgen_type, **kwargs): triangle_patch = Polygon(triangle_points, ec="k", fc="none") polys.append(triangle_patch) else: # Generic Patch - angle = angles[i] + try: + angle = angle_list[i] #Exception for index out of range in case of multiple elements of same type + except IndexError: + print("Index out of range!") + angle = angle_list[-1] + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angle) diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index 2307fd6bc..b71974307 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -18,6 +18,7 @@ from pandapower.plotting.generic_geodata import create_generic_coordinates from pandapower import get_connected_elements_dict import pandapower as pp +import math try: import pandaplan.core.pplog as logging @@ -183,26 +184,53 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g total_patches = len(get_connected_elements_dict(net, element_types=["sgen", "gen", "load"], buses=1)) + len( net.sgen.type.unique()) - patch_count_unique = [] #Unique patch on each node - for i in range(len(net.bus)): + + patch_count_unique = {} + + for i in range(1, len(net.bus)): # Start from index 1 instead of 0 + sgen_count = 0 + gen_count = 0 + load_count = 0 if plot_sgens and len(net.sgen): - patch_count_unique.insert(i, (len(net.sgen[net.sgen.bus == i].type.unique()))) - sgen_type = net.sgen.type - sgc = create_sgen_collection(net, sgen_type, size=sgen_size, orientation=orientation) - collections.append(sgc) + sgen_count = len(net.sgen[net.sgen.bus == i].type.unique()) + if plot_gens and len(net.gen): - patch_count_unique[i] += (len(pp.get_connected_elements_dict(net, element_types=["gen"], buses=i))) - gc = create_gen_collection(net, size=gen_size,orientation=orientation) - collections.append(gc) - if plot_loads and len(net.load): - patch_count_unique[i] += (len(pp.get_connected_elements_dict(net, element_types=["load"], buses=i))) - lc = create_load_collection(net, size=load_size,orientation=orientation) - collections.append(lc) + gen_count = len(pp.get_connected_elements_dict(net, element_types=["gen"], buses=i)) - if len(net.switch): - bsc = create_bus_bus_switch_collection(net, size=switch_size) - collections.append(bsc) + if plot_loads and len(net.load): + load_count = len(pp.get_connected_elements_dict(net, element_types=["load"], buses=i)) + + total_count = sgen_count + gen_count + load_count + + patch_count_unique[i] = { + 'sgen': [j * (2 * math.pi / total_count) for j in range(sgen_count)], + 'gen': [j * (2 * math.pi / total_count) + sgen_count * (2 * math.pi / total_count) for j in + range(gen_count)], + 'load': [j * (2 * math.pi / total_count) + (sgen_count + gen_count) * (2 * math.pi / total_count) for j in + range(load_count)] + } + + sgen_angle_list = [value["sgen"] for value in patch_count_unique.values() if "sgen" in value] + gen_angle_list = [value["gen"] for value in patch_count_unique.values() if "gen" in value] + load_angle_list = [value["load"] for value in patch_count_unique.values() if "load" in value] + if plot_sgens and len(net.sgen): + + sgen_type = net.sgen.type + sgc = create_sgen_collection(net, sgen_type, size=sgen_size,sgen_angle_list = sgen_angle_list, orientation=orientation) + collections.append(sgc) + if plot_gens and len(net.gen): + + gc = create_gen_collection(net, size=gen_size,gen_angle_list = gen_angle_list,orientation=orientation) + collections.append(gc) + if plot_loads and len(net.load): + + lc = create_load_collection(net, size=load_size,load_angle_list = load_angle_list,orientation=orientation) + collections.append(lc) + + if len(net.switch): + bsc = create_bus_bus_switch_collection(net, size=switch_size) + collections.append(bsc) ax = draw_collections(collections, ax=ax) if show_plot: From c3f59452e65531cb67b9c3f8c4134d4aedef10a4 Mon Sep 17 00:00:00 2001 From: hzraja Date: Wed, 21 Jun 2023 13:52:55 +0200 Subject: [PATCH 14/33] multiple patches v0.91 --- CHANGELOG.rst | 2 ++ pandapower/plotting/collections.py | 15 ++++++++ pandapower/plotting/patch_makers.py | 54 +++++++++++++---------------- pandapower/plotting/simple_plot.py | 11 ++++++ 4 files changed, 52 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2b113272b..4fe5a28b2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,7 @@ Change Log [upcoming release] - 2023-..-.. ------------------------------- +- [ADDED] patches for different sgen types - [ADDED] exporting to :code:`GeoJSON` with all properties from :code:`bus`, :code:`res_bus` and :code:`line`, :code:`res_line` - [ADDED] function to run powerflow using the power-grid-model library - [FIXED] short-circuit calculation: wrong results when :code:`ext_grid` and :code:`gen` elements are connected to the same bus @@ -16,6 +17,7 @@ Change Log - [FIXED] fixed bug in :code:`pp.select_subnet` when using tap dependent impedance + [2.13.1] - 2023-05-12 ------------------------------- - [FIXED] missing test files for CIM converter test in the release files diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index 7215dadd4..de6f77c15 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -1066,10 +1066,25 @@ def create_sgen_collection(net, sgen_type, sgens=None, size=1.,sgen_angle_list = **sgen_lc** - line collection """ + sgens_unique = [] + for bus in net.sgen.bus.unique(): + for type in net.sgen[net.sgen.bus == bus].type.unique(): + idx = net.sgen[(net.sgen.bus == bus) & (net.sgen.type == type)].index[0] + sgens_unique.append(idx) + + sgens = get_index_array(sgens, net.sgen.index) + sgens = sgens_unique + sgen_type = net.sgen.type.loc[sgens] + + + + + infos = [infofunc(i) for i in range(len(sgens))] if infofunc is not None else [] node_coords = net.bus_geodata.loc[net.sgen.loc[sgens, "bus"].values, ["x", "y"]].values + color = kwargs.pop("color", "k") sgen_pc, sgen_lc = _create_node_element_collection( node_coords, sgen_patches, sgen_type = sgen_type, size=size,angle_list=sgen_angle_list, infos=infos, orientation=orientation, diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 1bd7a0801..52789f334 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -8,7 +8,7 @@ from matplotlib.patches import RegularPolygon, Arc, Circle, Rectangle, Ellipse, Wedge, PathPatch, Polygon from matplotlib import text import matplotlib.path as mpath - import matplotlib.transforms as mtransforms + import matplotlib.transforms as transforms import math MATPLOTLIB_INSTALLED = True @@ -183,7 +183,7 @@ def load_patches(node_coords, size, angles,angle_list, **kwargs): """ if not MATPLOTLIB_INSTALLED: soft_dependency_error(str(sys._getframe().f_code.co_name)+"()", "matplotlib") - offset = kwargs.get("offset", 1.2 * size) + offset = kwargs.get("offset", 1.5 * size) all_angles = get_angle_list(angles, len(node_coords)) edgecolor = kwargs.get("patch_edgecolor", "w") facecolor = kwargs.get("patch_facecolor", "w") @@ -191,29 +191,25 @@ def load_patches(node_coords, size, angles,angle_list, **kwargs): facecolors = get_color_list(facecolor, len(node_coords)) polys, lines = list(), list() - flatten_list = [item for sublist in angle_list for item in sublist] - angle_list = flatten_list last_entry = angle_list.pop() angle_list.insert(0, last_entry) for i, node_geo in enumerate(node_coords): try: - angle = angle_list[i] #Exception for index out of range in case of multiple elements of same type + angle = angles[i] + angle_list[i] #Exception for index out of range in case of multiple elements of same type except IndexError: print("Index out of range!") - angle = angle_list[- 1] - p2 = node_geo + _rotate_dim2(np.array([0, offset + size]), angle ) + angle = angles[i] + angle_list[- 1] + p2 = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) p3 = node_geo + _rotate_dim2(np.array([0, offset + size / 2]), angle) - polys.append(RegularPolygon(p2, numVertices=3, radius=size, orientation=angle, + polys.append(RegularPolygon(p2, numVertices=3, radius=size, orientation=-angle, fc=facecolors[i], ec=edgecolors[i])) lines.append((node_geo, p3)) return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} - - def gen_patches(node_coords, size, angles, angle_list, **kwargs): """ Creation function of patches for generators. @@ -251,11 +247,13 @@ def gen_patches(node_coords, size, angles, angle_list, **kwargs): for i, node_geo in enumerate(node_coords): try: - angle = angle_list[i] #Exception for index out of range in case of multiple elements of same type + angle = angles[i] + angle_list[i] #Exception for index out of range in case of multiple elements of same type except IndexError: print("Index out of range!") - angle = angle_list[- 1] + angle = angles[i] + angle_list[- 1] p2 = node_geo + _rotate_dim2(np.array([0, size + offset]), angle) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) + polys.append(Circle(p2, size, fc=facecolors[i], ec=edgecolors[i])) polys.append( Arc(p2 + np.array([-size / 6.2, -size / 2.6]), size / 2, size, theta1=65, theta2=120, @@ -263,7 +261,7 @@ def gen_patches(node_coords, size, angles, angle_list, **kwargs): polys.append( Arc(p2 + np.array([size / 6.2, size / 2.6]), size / 2, size, theta1=245, theta2=300, ec=edgecolors[i])) - lines.append((node_geo, p2 + _rotate_dim2(np.array([0, size]), -angle))) + lines.append((node_geo, circ_edge)) return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} gen_printed = True @@ -297,6 +295,8 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): edgecolors = get_color_list(edgecolor, len(node_coords)) facecolors = get_color_list(facecolor, len(node_coords)) Path = mpath.Path + x = angle_list + #x.insert(0, x.pop()) flatten_list = [item for sublist in angle_list for item in sublist] @@ -306,12 +306,14 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): for i, node_geo in enumerate(node_coords): + try: + sgen_type[i] + except KeyError: + continue if sgen_type[i] == "WT": # Special patch for sgen_type "Wind Turbine" - try: #Exception for index out of range in case of multiple elements of same type - angle = angle_list[i] - except IndexError: - print("Index out of range!") - angle = angle_list[- 1] + # Exception for index out of range in case of multiple elements of same type + angle = angles[i] + angle_list[i] + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2 * size]), angle) @@ -354,14 +356,9 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): center_point = mid_midcirc # Define the center point of the wind turbine patch rotation_angle = math.pi / 4 # Define the angle of rotation - elif sgen_type[i] == "PV": # Special patch for sgen_type "Photo-voltaic" - try: - angle = angle_list[i] #Exception for index out of range in case of multiple elements of same type - except IndexError: - print("Index out of range!") - angle = angle_list[- 1] - mid_rect = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + angle = angles[i] + angle_list[i] #Exception for index out of range in case of multiple elements of same type + mid_rect = node_geo + _rotate_dim2(np.array([0, 2*size]), angle) rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] pv_patch = Rectangle((rect_lbottom), 0.05, 0.1, angle=-angle * (180 / np.pi), rotation_point=(mid_rect[0], mid_rect[1]), ec="k", fc="none") @@ -377,11 +374,8 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): triangle_patch = Polygon(triangle_points, ec="k", fc="none") polys.append(triangle_patch) else: # Generic Patch - try: - angle = angle_list[i] #Exception for index out of range in case of multiple elements of same type - except IndexError: - print("Index out of range!") - angle = angle_list[-1] + angle = angles[i] + angle_list[i] #Exception for index out of range in case of multiple elements of same type + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index b71974307..97e78f235 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -186,15 +186,24 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g net.sgen.type.unique()) patch_count_unique = {} + sgen_types = {} for i in range(1, len(net.bus)): # Start from index 1 instead of 0 sgen_count = 0 gen_count = 0 load_count = 0 + if plot_sgens and len(net.sgen): sgen_count = len(net.sgen[net.sgen.bus == i].type.unique()) + sgen_types_counts = net.sgen[net.sgen.bus == i].type.value_counts() + + sgen_types[i] = { + "WT": sgen_types_counts.get("WT", 0), + "PV": sgen_types_counts.get("PV", 0), + "wye": sgen_types_counts.get("wye", 0)} + if plot_gens and len(net.gen): gen_count = len(pp.get_connected_elements_dict(net, element_types=["gen"], buses=i)) @@ -204,6 +213,8 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g total_count = sgen_count + gen_count + load_count patch_count_unique[i] = { + + 'sgen': [j * (2 * math.pi / total_count) for j in range(sgen_count)], 'gen': [j * (2 * math.pi / total_count) + sgen_count * (2 * math.pi / total_count) for j in range(gen_count)], From fcf519628f1dde867c39335ac97efce071b76dba Mon Sep 17 00:00:00 2001 From: hzraja Date: Thu, 29 Jun 2023 12:10:24 +0200 Subject: [PATCH 15/33] multiple patches v0.92 --- pandapower/plotting/collections.py | 2 +- pandapower/plotting/patch_makers.py | 27 +++++++++----------- pandapower/plotting/simple_plot.py | 38 +++++++++++++++++------------ 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index de6f77c15..eb6c82fcd 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -1082,7 +1082,7 @@ def create_sgen_collection(net, sgen_type, sgens=None, size=1.,sgen_angle_list = infos = [infofunc(i) for i in range(len(sgens))] if infofunc is not None else [] - node_coords = net.bus_geodata.loc[net.sgen.loc[sgens, "bus"].values, ["x", "y"]].values + node_coords = net.bus_geodata.loc[:, ["x", "y"]] color = kwargs.pop("color", "k") diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 52789f334..674e97f19 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -298,21 +298,17 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): x = angle_list #x.insert(0, x.pop()) - flatten_list = [item for sublist in angle_list for item in sublist] + #flatten_list = [item for sublist in angle_list for item in sublist] - angle_list = flatten_list - last_entry = angle_list.pop() - angle_list.insert(0, last_entry) - for i, node_geo in enumerate(node_coords): - try: - sgen_type[i] - except KeyError: - continue - if sgen_type[i] == "WT": # Special patch for sgen_type "Wind Turbine" + + + for i in node_coords.index: + node_geo = list(node_coords.loc[i]) + if "WT" in angle_list[i]["sgen"]: # Special patch for sgen_type "Wind Turbine" # Exception for index out of range in case of multiple elements of same type - angle = angles[i] + angle_list[i] + angle = angle_list[i]["sgen"]["WT"] mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) @@ -356,8 +352,9 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): center_point = mid_midcirc # Define the center point of the wind turbine patch rotation_angle = math.pi / 4 # Define the angle of rotation - elif sgen_type[i] == "PV": # Special patch for sgen_type "Photo-voltaic" - angle = angles[i] + angle_list[i] #Exception for index out of range in case of multiple elements of same type + if "PV" in angle_list[i]["sgen"]: # Special patch for sgen_type "Wind Turbine" + # Exception for index out of range in case of multiple elements of same type + angle = angle_list[i]["sgen"]["PV"] #ase of multiple elements of same type mid_rect = node_geo + _rotate_dim2(np.array([0, 2*size]), angle) rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] pv_patch = Rectangle((rect_lbottom), 0.05, 0.1, angle=-angle * (180 / np.pi), @@ -373,8 +370,8 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): ] triangle_patch = Polygon(triangle_points, ec="k", fc="none") polys.append(triangle_patch) - else: # Generic Patch - angle = angles[i] + angle_list[i] #Exception for index out of range in case of multiple elements of same type + if "wye" in angle_list[i]["sgen"]: # Generic Patch + angle = angles[i] + angle_list[i]["sgen"]["wye"] #Exception for index out of range in case of multiple elements of same type mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index 97e78f235..9daa4fb63 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -188,21 +188,28 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g patch_count_unique = {} sgen_types = {} - for i in range(1, len(net.bus)): # Start from index 1 instead of 0 - sgen_count = 0 + for i in net.bus_geodata.index: # Start from index 1 instead of 0 + #sgen_types = 0 gen_count = 0 load_count = 0 if plot_sgens and len(net.sgen): - sgen_count = len(net.sgen[net.sgen.bus == i].type.unique()) + #sgen_types = net.sgen[net.sgen.bus == i].type.unique() sgen_types_counts = net.sgen[net.sgen.bus == i].type.value_counts() - sgen_types[i] = { - "WT": sgen_types_counts.get("WT", 0), - "PV": sgen_types_counts.get("PV", 0), - "wye": sgen_types_counts.get("wye", 0)} + PV = sgen_types_counts.get("PV", 0) + WT = sgen_types_counts.get("WT", 0) + WYE = sum(sgen_types_counts) - PV - WT + types = {} + if PV: + types["PV"] = PV + if WT: + types["WT"] = WT + if WYE: + types["wye"] = WYE + sgen_types[i] = types if plot_gens and len(net.gen): gen_count = len(pp.get_connected_elements_dict(net, element_types=["gen"], buses=i)) @@ -210,25 +217,24 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g if plot_loads and len(net.load): load_count = len(pp.get_connected_elements_dict(net, element_types=["load"], buses=i)) - total_count = sgen_count + gen_count + load_count - + total_count = len(sgen_types[i]) + gen_count + load_count + try: seperation_angle = 2 * math.pi / total_count + except ZeroDivisionError: seperation_angle = None patch_count_unique[i] = { - - 'sgen': [j * (2 * math.pi / total_count) for j in range(sgen_count)], - 'gen': [j * (2 * math.pi / total_count) + sgen_count * (2 * math.pi / total_count) for j in + 'sgen': dict(zip(sgen_types[i].keys(), [j * (2 * math.pi / total_count) for j in range(len(sgen_types[i]))])), + 'gen': [j * (2 * math.pi / total_count) + len(sgen_types[i]) * (2 * math.pi / total_count) for j in range(gen_count)], - 'load': [j * (2 * math.pi / total_count) + (sgen_count + gen_count) * (2 * math.pi / total_count) for j in - range(load_count)] + 'load': [j * (2 * math.pi / total_count) + (len(sgen_types[i]) + gen_count) * (2 * math.pi / total_count) for j in range(load_count)] } - sgen_angle_list = [value["sgen"] for value in patch_count_unique.values() if "sgen" in value] + #sgen_angle_list = [value["sgen"] for value in patch_count_unique.values() if "sgen" in value] gen_angle_list = [value["gen"] for value in patch_count_unique.values() if "gen" in value] load_angle_list = [value["load"] for value in patch_count_unique.values() if "load" in value] if plot_sgens and len(net.sgen): sgen_type = net.sgen.type - sgc = create_sgen_collection(net, sgen_type, size=sgen_size,sgen_angle_list = sgen_angle_list, orientation=orientation) + sgc = create_sgen_collection(net, sgen_type, size=sgen_size,sgen_angle_list = patch_count_unique, orientation=orientation) collections.append(sgc) if plot_gens and len(net.gen): From 298912837395e65d654bdb6fc31907203e590384 Mon Sep 17 00:00:00 2001 From: hzraja Date: Tue, 4 Jul 2023 11:00:00 +0200 Subject: [PATCH 16/33] multiple patches v0.93 --- pandapower/plotting/patch_makers.py | 72 +++++++++++++++-------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 674e97f19..64ea78fa6 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -8,7 +8,7 @@ from matplotlib.patches import RegularPolygon, Arc, Circle, Rectangle, Ellipse, Wedge, PathPatch, Polygon from matplotlib import text import matplotlib.path as mpath - import matplotlib.transforms as transforms + # import matplotlib.transforms as transforms import math MATPLOTLIB_INSTALLED = True @@ -197,11 +197,9 @@ def load_patches(node_coords, size, angles,angle_list, **kwargs): angle_list.insert(0, last_entry) for i, node_geo in enumerate(node_coords): - try: - angle = angles[i] + angle_list[i] #Exception for index out of range in case of multiple elements of same type - except IndexError: - print("Index out of range!") - angle = angles[i] + angle_list[- 1] + + angle = angles[i] + angle_list[i] + p2 = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) p3 = node_geo + _rotate_dim2(np.array([0, offset + size / 2]), angle) polys.append(RegularPolygon(p2, numVertices=3, radius=size, orientation=-angle, @@ -246,11 +244,9 @@ def gen_patches(node_coords, size, angles, angle_list, **kwargs): for i, node_geo in enumerate(node_coords): - try: - angle = angles[i] + angle_list[i] #Exception for index out of range in case of multiple elements of same type - except IndexError: - print("Index out of range!") - angle = angles[i] + angle_list[- 1] + + angle = angles[i] + angle_list[i] + p2 = node_geo + _rotate_dim2(np.array([0, size + offset]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) @@ -289,16 +285,16 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): polys, lines = list(), list() offset = kwargs.get("offset", 2 * size) r_triangle = kwargs.get("r_triangles", size * 0.4) - midcirc_size = size * 0.15 + hub_size = size * 0.15 # Hub size + blade_coord1 = size * 0.08 # Blade angle coord + blade_coord2 = size * 0.22 + pv_rect_size = size*2 + pv_tri_size = size edgecolor = kwargs.get("patch_edgecolor", "w") facecolor = kwargs.get("patch_facecolor", "w") edgecolors = get_color_list(edgecolor, len(node_coords)) facecolors = get_color_list(facecolor, len(node_coords)) Path = mpath.Path - x = angle_list - #x.insert(0, x.pop()) - - #flatten_list = [item for sublist in angle_list for item in sublist] @@ -307,8 +303,10 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): for i in node_coords.index: node_geo = list(node_coords.loc[i]) if "WT" in angle_list[i]["sgen"]: # Special patch for sgen_type "Wind Turbine" - # Exception for index out of range in case of multiple elements of same type - angle = angle_list[i]["sgen"]["WT"] + try: + angle = angle_list[i]["sgen"]["WT"] + angles[i] + except IndexError: + continue mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) @@ -317,11 +315,11 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): codes, verts = zip(*[ (Path.MOVETO, mid_midcirc), - (Path.LINETO, circ_topedge), - (Path.LINETO, (circ_topedge + _rotate_dim2(np.array([- 0.003, - 0.003]), angle)),), - (Path.LINETO, (mid_midcirc + _rotate_dim2(np.array([- 0.007, + 0.007]), angle)),), # Blade1 + (Path.LINETO, circ_topedge,), + (Path.LINETO, (circ_topedge + _rotate_dim2(np.array([- blade_coord1, - blade_coord1 ]), angle)),), + (Path.LINETO, (mid_midcirc + _rotate_dim2(np.array([- blade_coord2, + blade_coord2]), angle)),), # Blade1 (Path.CLOSEPOLY, mid_midcirc)]) - polys.append(PathPatch(mpath.Path(verts, codes), fc="k", ec="none")) + polys.append(PathPatch(mpath.Path(verts, codes), fc="k", ec="none",lw=200000000)) polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) lines.append((node_geo, circ_edge)) @@ -347,32 +345,36 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): polys.append(rotated_patch) - polys.append(Circle(mid_midcirc, midcirc_size, fc="k", ec=edgecolors[i])) # Center hub + polys.append(Circle(mid_midcirc, hub_size, fc="k", ec=edgecolors[i])) # Center hub center_point = mid_midcirc # Define the center point of the wind turbine patch rotation_angle = math.pi / 4 # Define the angle of rotation - if "PV" in angle_list[i]["sgen"]: # Special patch for sgen_type "Wind Turbine" - # Exception for index out of range in case of multiple elements of same type - angle = angle_list[i]["sgen"]["PV"] #ase of multiple elements of same type + if "PV" in angle_list[i]["sgen"]: + try: + angle = angle_list[i]["sgen"]["PV"] + angles[i] + except IndexError: + continue mid_rect = node_geo + _rotate_dim2(np.array([0, 2*size]), angle) - rect_lbottom = [mid_rect[0] - 0.025, mid_rect[1]] - pv_patch = Rectangle((rect_lbottom), 0.05, 0.1, angle=-angle * (180 / np.pi), + rect_lbottom = [mid_rect[0] - (pv_rect_size/4), mid_rect[1]] + pv_patch = Rectangle((rect_lbottom), pv_rect_size/2, pv_rect_size, angle=-angle * (180 / np.pi), rotation_point=(mid_rect[0], mid_rect[1]), ec="k", fc="none") polys.append(pv_patch) lines.append((node_geo, mid_rect)) - triangle_base = 0.05 - triangle_height = 0.06 + triangle_base = pv_tri_size + triangle_height = pv_tri_size * 0.75 triangle_points = [ - (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 0.1]), angle)), - (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 0.1]), angle)), - (mid_rect + _rotate_dim2(np.array([0, + triangle_height]), angle)), + (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 2*size]), angle)), + (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 2*size]), angle)), + (mid_rect + _rotate_dim2(np.array([0, + 1.5*triangle_height]), angle)), ] triangle_patch = Polygon(triangle_points, ec="k", fc="none") polys.append(triangle_patch) if "wye" in angle_list[i]["sgen"]: # Generic Patch - angle = angles[i] + angle_list[i]["sgen"]["wye"] #Exception for index out of range in case of multiple elements of same type - + try: + angle = angle_list[i]["sgen"]["wye"] + angles[i] + except IndexError: + continue mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) From b957c263a7e8ac5a556d5c816287935261600f19 Mon Sep 17 00:00:00 2001 From: hzraja Date: Tue, 4 Jul 2023 14:59:51 +0200 Subject: [PATCH 17/33] multiple patches v0.95 --- CHANGELOG.rst | 1 - pandapower/plotting/collections.py | 36 ++++--------- pandapower/plotting/patch_makers.py | 84 +++++++++++++---------------- pandapower/plotting/simple_plot.py | 22 ++------ 4 files changed, 52 insertions(+), 91 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4fe5a28b2..5cfb77d5a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,7 +3,6 @@ Change Log [upcoming release] - 2023-..-.. ------------------------------- -- [ADDED] patches for different sgen types - [ADDED] exporting to :code:`GeoJSON` with all properties from :code:`bus`, :code:`res_bus` and :code:`line`, :code:`res_line` - [ADDED] function to run powerflow using the power-grid-model library - [FIXED] short-circuit calculation: wrong results when :code:`ext_grid` and :code:`gen` elements are connected to the same bus diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index eb6c82fcd..8aabc95a0 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -222,7 +222,7 @@ def _create_line2d_collection(coords, indices, infos=None, picker=False, **kwarg return lc -def _create_node_element_collection(node_coords, patch_maker,sgen_type = None , size=1., angle_list = None, infos=None, +def _create_node_element_collection(node_coords, patch_maker, size=1., unique_angles=None, infos=None, repeat_infos=(1, 1), orientation=np.pi, picker=False, patch_facecolor="w", patch_edgecolor="k", line_color="k", **kwargs): @@ -278,7 +278,7 @@ def _create_node_element_collection(node_coords, patch_maker,sgen_type = None , linewidths = kwargs.pop("linewidth", linewidths) linewidths = kwargs.pop("lw", linewidths) lines, polys, popped_keywords = patch_maker( - node_coords, size, angles, sgen_type=sgen_type, angle_list=angle_list, patch_facecolor=patch_facecolor, patch_edgecolor=patch_edgecolor, + node_coords, size, angles, unique_angles=unique_angles, patch_facecolor=patch_facecolor, patch_edgecolor=patch_edgecolor, **kwargs) for kw in set(popped_keywords) & set(kwargs.keys()): kwargs.pop(kw) @@ -959,7 +959,7 @@ def create_busbar_collection(net, buses=None, infofunc=None, cmap=None, norm=Non return lc -def create_load_collection(net, loads=None, size=1.,load_angle_list = None, patch_count = None, infofunc=None, orientation=None, picker=False, +def create_load_collection(net, loads=None, size=1., unique_angles=None, patch_count = None, infofunc=None, orientation=None, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower loads. @@ -990,17 +990,17 @@ def create_load_collection(net, loads=None, size=1.,load_angle_list = None, patc loads = get_index_array(loads, net.load.index) infos = [infofunc(i) for i in range(len(loads))] if infofunc is not None else [] - node_coords = net.bus_geodata.loc[net.load.loc[loads, "bus"].values, ["x", "y"]].values + node_coords = net.bus_geodata.loc[:, ["x", "y"]] color = kwargs.pop("color", "k") load_pc, load_lc = _create_node_element_collection( - node_coords, load_patches, size=size,angle_list=load_angle_list, infos=infos, orientation=orientation, + node_coords, load_patches, size=size, unique_angles=unique_angles, infos=infos, orientation=orientation, picker=picker, line_color=color, **kwargs) return load_pc, load_lc -def create_gen_collection(net, gens=None, size=1.,gen_angle_list=None,patch_count=None, infofunc=None, orientation=None, picker=False, +def create_gen_collection(net, gens=None, size=1., unique_angles=None, patch_count=None, infofunc=None, orientation=None, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower gens. @@ -1029,17 +1029,17 @@ def create_gen_collection(net, gens=None, size=1.,gen_angle_list=None,patch_coun """ gens = get_index_array(gens, net.gen.index) infos = [infofunc(i) for i in range(len(gens))] if infofunc is not None else [] - node_coords = net.bus_geodata.loc[net.gen.loc[gens, "bus"].values, ["x", "y"]].values + node_coords = net.bus_geodata.loc[:, ["x", "y"]] color = kwargs.pop("color", "k") gen_pc, gen_lc = _create_node_element_collection( - node_coords, gen_patches, size=size,angle_list=gen_angle_list, infos=infos, orientation=orientation, + node_coords, gen_patches, size=size, unique_angles=unique_angles, infos=infos, orientation=orientation, picker=picker, line_color=color, **kwargs) return gen_pc, gen_lc -def create_sgen_collection(net, sgen_type, sgens=None, size=1.,sgen_angle_list = None, infofunc=None, orientation=None, picker=False, +def create_sgen_collection(net, sgens=None, size=1., unique_angles=None, infofunc=None, orientation=None, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower sgen. @@ -1066,20 +1066,6 @@ def create_sgen_collection(net, sgen_type, sgens=None, size=1.,sgen_angle_list = **sgen_lc** - line collection """ - sgens_unique = [] - for bus in net.sgen.bus.unique(): - for type in net.sgen[net.sgen.bus == bus].type.unique(): - idx = net.sgen[(net.sgen.bus == bus) & (net.sgen.type == type)].index[0] - sgens_unique.append(idx) - - - sgens = get_index_array(sgens, net.sgen.index) - sgens = sgens_unique - sgen_type = net.sgen.type.loc[sgens] - - - - infos = [infofunc(i) for i in range(len(sgens))] if infofunc is not None else [] node_coords = net.bus_geodata.loc[:, ["x", "y"]] @@ -1087,7 +1073,7 @@ def create_sgen_collection(net, sgen_type, sgens=None, size=1.,sgen_angle_list = color = kwargs.pop("color", "k") sgen_pc, sgen_lc = _create_node_element_collection( - node_coords, sgen_patches, sgen_type = sgen_type, size=size,angle_list=sgen_angle_list, infos=infos, orientation=orientation, + node_coords, sgen_patches, size=size, unique_angles=unique_angles, infos=infos, orientation=orientation, picker=picker, line_color=color, **kwargs) return sgen_pc, sgen_lc @@ -1173,7 +1159,7 @@ def create_ext_grid_collection(net, size=1., infofunc=None, orientation=0, picke color = kwargs.pop("color", "k") ext_grid_pc, ext_grid_lc = _create_node_element_collection( - node_coords, ext_grid_patches,sgen_type, size=size, infos=infos, orientation=orientation, + node_coords, ext_grid_patches, size=size, infos=infos, orientation=orientation, picker=picker, hatch='XXX', line_color=color, **kwargs) return ext_grid_pc, ext_grid_lc diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 64ea78fa6..0a2c6f71f 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -163,7 +163,7 @@ def polygon_patches(node_coords, radius, num_edges, color=None, **kwargs): -def load_patches(node_coords, size, angles,angle_list, **kwargs): +def load_patches(node_coords, size, angles, unique_angles, **kwargs): """ Creation function of patches for loads. @@ -191,24 +191,22 @@ def load_patches(node_coords, size, angles,angle_list, **kwargs): facecolors = get_color_list(facecolor, len(node_coords)) polys, lines = list(), list() - flatten_list = [item for sublist in angle_list for item in sublist] - angle_list = flatten_list - last_entry = angle_list.pop() - angle_list.insert(0, last_entry) - - for i, node_geo in enumerate(node_coords): - - angle = angles[i] + angle_list[i] + for i in node_coords.index: + node_geo = list(node_coords.loc[i]) + if "load" in unique_angles[i]: + try: + angle = unique_angles[i]["load"][0] + all_angles[i] + except IndexError: + continue - p2 = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) - p3 = node_geo + _rotate_dim2(np.array([0, offset + size / 2]), angle) - polys.append(RegularPolygon(p2, numVertices=3, radius=size, orientation=-angle, - fc=facecolors[i], ec=edgecolors[i])) - lines.append((node_geo, p3)) + p2 = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + p3 = node_geo + _rotate_dim2(np.array([0, offset + size / 2]), angle) + polys.append(RegularPolygon(p2, numVertices=3, radius=size, orientation=-angle,fc = "w",ec="k")) + lines.append((node_geo, p3)) return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} -def gen_patches(node_coords, size, angles, angle_list, **kwargs): +def gen_patches(node_coords, size, angles, unique_angles, **kwargs): """ Creation function of patches for generators. @@ -236,33 +234,29 @@ def gen_patches(node_coords, size, angles, angle_list, **kwargs): edgecolors = get_color_list(edgecolor, len(node_coords)) facecolors = get_color_list(facecolor, len(node_coords)) - flatten_list = [item for sublist in angle_list for item in sublist] - - angle_list = flatten_list - last_entry = angle_list.pop() - angle_list.insert(0, last_entry) - - - for i, node_geo in enumerate(node_coords): - - angle = angles[i] + angle_list[i] - - p2 = node_geo + _rotate_dim2(np.array([0, size + offset]), angle) - circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) + for i in node_coords.index: + node_geo = list(node_coords.loc[i]) + if "gen" in unique_angles[i]: + try: + angle = unique_angles[i]["gen"][0] + all_angles[i] + except IndexError: + continue - polys.append(Circle(p2, size, fc=facecolors[i], ec=edgecolors[i])) - polys.append( - Arc(p2 + np.array([-size / 6.2, -size / 2.6]), size / 2, size, theta1=65, theta2=120, - ec=edgecolors[i])) - polys.append( - Arc(p2 + np.array([size / 6.2, size / 2.6]), size / 2, size, theta1=245, theta2=300, - ec=edgecolors[i])) - lines.append((node_geo, circ_edge)) + p2 = node_geo + _rotate_dim2(np.array([0, size + offset]), angle) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) + polys.append(Circle(p2, size, fc=facecolors[i], ec=edgecolors[i])) + polys.append( + Arc(p2 + np.array([-size / 6.2, -size / 2.6]), size / 2, size, theta1=65, theta2=120, + ec=edgecolors[i])) + polys.append( + Arc(p2 + np.array([size / 6.2, size / 2.6]), size / 2, size, theta1=245, theta2=300, + ec=edgecolors[i])) + lines.append((node_geo, circ_edge)) return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} gen_printed = True -def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): +def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): """ Creation function of patches for static generators. @@ -296,15 +290,11 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): facecolors = get_color_list(facecolor, len(node_coords)) Path = mpath.Path - - - - for i in node_coords.index: node_geo = list(node_coords.loc[i]) - if "WT" in angle_list[i]["sgen"]: # Special patch for sgen_type "Wind Turbine" + if "WT" in unique_angles[i]["sgen"]: # WT patch try: - angle = angle_list[i]["sgen"]["WT"] + angles[i] + angle = unique_angles[i]["sgen"]["WT"] + angles[i] except IndexError: continue @@ -350,9 +340,9 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): center_point = mid_midcirc # Define the center point of the wind turbine patch rotation_angle = math.pi / 4 # Define the angle of rotation - if "PV" in angle_list[i]["sgen"]: + if "PV" in unique_angles[i]["sgen"]: # PV patch try: - angle = angle_list[i]["sgen"]["PV"] + angles[i] + angle = unique_angles[i]["sgen"]["PV"] + angles[i] except IndexError: continue mid_rect = node_geo + _rotate_dim2(np.array([0, 2*size]), angle) @@ -370,9 +360,9 @@ def sgen_patches(node_coords, size, angles,sgen_type,angle_list, **kwargs): ] triangle_patch = Polygon(triangle_points, ec="k", fc="none") polys.append(triangle_patch) - if "wye" in angle_list[i]["sgen"]: # Generic Patch + if "wye" in unique_angles[i]["sgen"]: # Generic Patch try: - angle = angle_list[i]["sgen"]["wye"] + angles[i] + angle = unique_angles[i]["sgen"]["wye"] + angles[i] except IndexError: continue diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index 9daa4fb63..d88385c06 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -171,11 +171,6 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g color=trafo_color) collections.append(tc) - #TODO Calculate patch angles based on number of elements here - # get_connected_elements_dict - # unique() - - if plot_line_switches and len(net.switch): sc = create_line_switch_collection( net, size=switch_size, distance_to_bus=switch_distance, @@ -188,17 +183,13 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g patch_count_unique = {} sgen_types = {} - for i in net.bus_geodata.index: # Start from index 1 instead of 0 - #sgen_types = 0 + for i in net.bus_geodata.index: gen_count = 0 load_count = 0 if plot_sgens and len(net.sgen): - #sgen_types = net.sgen[net.sgen.bus == i].type.unique() - sgen_types_counts = net.sgen[net.sgen.bus == i].type.value_counts() - PV = sgen_types_counts.get("PV", 0) WT = sgen_types_counts.get("WT", 0) WYE = sum(sgen_types_counts) - PV - WT @@ -228,21 +219,16 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g 'load': [j * (2 * math.pi / total_count) + (len(sgen_types[i]) + gen_count) * (2 * math.pi / total_count) for j in range(load_count)] } - #sgen_angle_list = [value["sgen"] for value in patch_count_unique.values() if "sgen" in value] - gen_angle_list = [value["gen"] for value in patch_count_unique.values() if "gen" in value] - load_angle_list = [value["load"] for value in patch_count_unique.values() if "load" in value] if plot_sgens and len(net.sgen): - - sgen_type = net.sgen.type - sgc = create_sgen_collection(net, sgen_type, size=sgen_size,sgen_angle_list = patch_count_unique, orientation=orientation) + sgc = create_sgen_collection(net, size=sgen_size, unique_angles=patch_count_unique, orientation=orientation) collections.append(sgc) if plot_gens and len(net.gen): - gc = create_gen_collection(net, size=gen_size,gen_angle_list = gen_angle_list,orientation=orientation) + gc = create_gen_collection(net, size=gen_size, unique_angles=patch_count_unique, orientation=orientation) collections.append(gc) if plot_loads and len(net.load): - lc = create_load_collection(net, size=load_size,load_angle_list = load_angle_list,orientation=orientation) + lc = create_load_collection(net, size=load_size, unique_angles=patch_count_unique, orientation=orientation) collections.append(lc) if len(net.switch): From 5e2d93fa0b0311c4c00f5505f9d748614e3983d6 Mon Sep 17 00:00:00 2001 From: hzraja Date: Tue, 4 Jul 2023 15:47:57 +0200 Subject: [PATCH 18/33] multiple patches v0.95 (updated changelog and doc-string) --- CHANGELOG.rst | 1 + pandapower/plotting/collections.py | 8 ++++++++ pandapower/plotting/patch_makers.py | 8 ++++++++ 3 files changed, 17 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e5d894d29..118fc5c4a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,7 @@ Change Log [upcoming release] - 2023-..-.. ------------------------------- +- [ADDED] a patch for PV-plants (:code:`sgen.type = "PV"`) and Windturbines (:code:`sgen.type = "WT"`) to :code:`simple_plot` - [ADDED] exporting to :code:`GeoJSON` with all properties from :code:`bus`, :code:`res_bus` and :code:`line`, :code:`res_line` - [ADDED] function to run powerflow using the power-grid-model library - [FIXED] short-circuit calculation: wrong results when :code:`ext_grid` and :code:`gen` elements are connected to the same bus diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index 8aabc95a0..570d4e754 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -238,6 +238,8 @@ def _create_node_element_collection(node_coords, patch_maker, size=1., unique_an :type patch_maker: function :param size: patch size :type size: float, default 1 + :param unique_angles: angles for patches + :type size: dict :param infos: list of infos belonging to each of the elements (can be displayed when hovering \ over them) :type infos: iterable, default None @@ -972,6 +974,8 @@ def create_load_collection(net, loads=None, size=1., unique_angles=None, patch_c **size** (float, 1) - patch size + **unique_angles** {dict} angles for patches + **infofunc** (function, None) - infofunction for the patch element **orientation** (float, np.pi) - orientation of load collection. pi is directed downwards, @@ -1013,6 +1017,8 @@ def create_gen_collection(net, gens=None, size=1., unique_angles=None, patch_cou **size** (float, 1) - patch size + **unique_angles** {dict} angles for patches + **infofunc** (function, None) - infofunction for the patch element **orientation** (float or list of floats, np.pi) - orientation of gen collection. pi is\ @@ -1052,6 +1058,8 @@ def create_sgen_collection(net, sgens=None, size=1., unique_angles=None, infofun **size** (float, 1) - patch size + **unique_angles** {dict} angles for patches + **infofunc** (function, None) - infofunction for the patch elem **picker** (bool, False) - picker argument passed to the patch collectionent diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 0a2c6f71f..b016c0654 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -173,6 +173,10 @@ def load_patches(node_coords, size, angles, unique_angles, **kwargs): :type size: float :param angles: angles by which to rotate the patches (in radians) :type angles: iterable(float), float + :param unique_angles: angles for patches + :param unique_angles: angles for patches + :type size: dict + :type size: dict :param kwargs: additional keyword arguments (might contain parameters "offset",\ "patch_edgecolor" and "patch_facecolor") :type kwargs: @@ -216,6 +220,8 @@ def gen_patches(node_coords, size, angles, unique_angles, **kwargs): :type size: float :param angles: angles by which to rotate the patches (in radians) :type angles: iterable(float), float + :param unique_angles: angles for patches + :type size: dict :param kwargs: additional keyword arguments (might contain parameters "offset",\ "patch_edgecolor" and "patch_facecolor") :type kwargs: @@ -266,6 +272,8 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): :type size: float :param angles: angles by which to rotate the patches (in radians) :type angles: iterable(float), float + :param unique_angles: angles for patches + :type size: dict :param kwargs: additional keyword arguments (might contain parameters "offset", "r_triangle",\ "patch_edgecolor" and "patch_facecolor") :type kwargs: From 89d5e0ca0f26cfee9ece8cca8dd2db4521cf01d8 Mon Sep 17 00:00:00 2001 From: Jan Wiemer <32835953+jwiemer112@users.noreply.github.com> Date: Tue, 4 Jul 2023 15:51:20 +0200 Subject: [PATCH 19/33] Update CHANGELOG.rst --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 118fc5c4a..a16be3b77 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,7 +3,7 @@ Change Log [upcoming release] - 2023-..-.. ------------------------------- -- [ADDED] a patch for PV-plants (:code:`sgen.type = "PV"`) and Windturbines (:code:`sgen.type = "WT"`) to :code:`simple_plot` +- [ADDED] patches for PV-plants (:code:`sgen.type = "PV"`) and Windturbines (:code:`sgen.type = "WT"`) to :code:`simple_plot` - [ADDED] exporting to :code:`GeoJSON` with all properties from :code:`bus`, :code:`res_bus` and :code:`line`, :code:`res_line` - [ADDED] function to run powerflow using the power-grid-model library - [FIXED] short-circuit calculation: wrong results when :code:`ext_grid` and :code:`gen` elements are connected to the same bus From 2bb422044548f826264afce3deec05352fc5533b Mon Sep 17 00:00:00 2001 From: hzraja Date: Tue, 4 Jul 2023 16:02:04 +0200 Subject: [PATCH 20/33] removed unused argument (patch_count) --- pandapower/plotting/collections.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index 570d4e754..b4da3f069 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -961,7 +961,7 @@ def create_busbar_collection(net, buses=None, infofunc=None, cmap=None, norm=Non return lc -def create_load_collection(net, loads=None, size=1., unique_angles=None, patch_count = None, infofunc=None, orientation=None, picker=False, +def create_load_collection(net, loads=None, size=1., unique_angles=None, infofunc=None, orientation=None, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower loads. @@ -1004,7 +1004,7 @@ def create_load_collection(net, loads=None, size=1., unique_angles=None, patch_c return load_pc, load_lc -def create_gen_collection(net, gens=None, size=1., unique_angles=None, patch_count=None, infofunc=None, orientation=None, picker=False, +def create_gen_collection(net, gens=None, size=1., unique_angles=None, infofunc=None, orientation=None, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower gens. From e15487e46ad873d6a448e9d533b95f3d51a0cfaa Mon Sep 17 00:00:00 2001 From: hzraja Date: Wed, 5 Jul 2023 12:39:29 +0200 Subject: [PATCH 21/33] fixed simple_plot bugs to adapt to tutorial --- pandapower/plotting/patch_makers.py | 14 +-- pandapower/plotting/simple_plot.py | 50 ++++++++--- tutorials/distributed_slack.ipynb | 128 ++++++++++++++++------------ 3 files changed, 117 insertions(+), 75 deletions(-) diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index b016c0654..282112e18 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -197,9 +197,9 @@ def load_patches(node_coords, size, angles, unique_angles, **kwargs): for i in node_coords.index: node_geo = list(node_coords.loc[i]) - if "load" in unique_angles[i]: + if "load" in unique_angles[i] and unique_angles[i]["load"] != []: try: - angle = unique_angles[i]["load"][0] + all_angles[i] + angle = (unique_angles[i]["load"][0]) + (all_angles[i] or 0) except IndexError: continue @@ -242,9 +242,9 @@ def gen_patches(node_coords, size, angles, unique_angles, **kwargs): for i in node_coords.index: node_geo = list(node_coords.loc[i]) - if "gen" in unique_angles[i]: + if "gen" in unique_angles[i] and unique_angles[i]["gen"] != []: try: - angle = unique_angles[i]["gen"][0] + all_angles[i] + angle = (unique_angles[i]["gen"][0]) + (all_angles[i] or 0) except IndexError: continue @@ -302,7 +302,7 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): node_geo = list(node_coords.loc[i]) if "WT" in unique_angles[i]["sgen"]: # WT patch try: - angle = unique_angles[i]["sgen"]["WT"] + angles[i] + angle = unique_angles[i]["sgen"]["WT"] + (angles[i] or 0) except IndexError: continue @@ -350,7 +350,7 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): if "PV" in unique_angles[i]["sgen"]: # PV patch try: - angle = unique_angles[i]["sgen"]["PV"] + angles[i] + angle = unique_angles[i]["sgen"]["PV"] + (angles[i] or 0) except IndexError: continue mid_rect = node_geo + _rotate_dim2(np.array([0, 2*size]), angle) @@ -370,7 +370,7 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): polys.append(triangle_patch) if "wye" in unique_angles[i]["sgen"]: # Generic Patch try: - angle = unique_angles[i]["sgen"]["wye"] + angles[i] + angle = unique_angles[i]["sgen"]["wye"] + (angles[i] or 0) except IndexError: continue diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index d88385c06..dea5ba1ab 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -184,9 +184,28 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g sgen_types = {} for i in net.bus_geodata.index: + sgen_count = 0 gen_count = 0 load_count = 0 - + sgen_key = {} + if plot_sgens and len(net.sgen): + try: + sgen_count = len(sgen_types[i]) + except KeyError: + sgen_count = 0 + if plot_gens and len(net.gen): + try: + gen_count = len(pp.get_connected_elements_dict(net, element_types=["gen"], buses=i)) + except KeyError: + gen_count = 0 + if plot_loads and len(net.load): + try: + load_count = len(pp.get_connected_elements_dict(net, element_types=["load"], buses=i)) + except KeyError: + load_count = 0 + total_count = sgen_count + gen_count + load_count + try: seperation_angle = 2 * math.pi / total_count + except ZeroDivisionError: seperation_angle = None if plot_sgens and len(net.sgen): sgen_types_counts = net.sgen[net.sgen.bus == i].type.value_counts() @@ -201,23 +220,26 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g if WYE: types["wye"] = WYE sgen_types[i] = types + if i not in patch_count_unique: + patch_count_unique[i] = {} + patch_count_unique[i]['sgen'] = dict( + zip(sgen_types[i].keys(), [j * seperation_angle for j in range(sgen_count)])) if plot_gens and len(net.gen): - gen_count = len(pp.get_connected_elements_dict(net, element_types=["gen"], buses=i)) + if i not in patch_count_unique: + patch_count_unique[i] = {} + if 'gen' not in patch_count_unique[i]: + patch_count_unique[i]['gen'] = [] + patch_count_unique[i]['gen'].extend( + [j * seperation_angle + sgen_count * seperation_angle for j in range(gen_count)]) if plot_loads and len(net.load): - load_count = len(pp.get_connected_elements_dict(net, element_types=["load"], buses=i)) - - total_count = len(sgen_types[i]) + gen_count + load_count - try: seperation_angle = 2 * math.pi / total_count - except ZeroDivisionError: seperation_angle = None - patch_count_unique[i] = { - - 'sgen': dict(zip(sgen_types[i].keys(), [j * (2 * math.pi / total_count) for j in range(len(sgen_types[i]))])), - 'gen': [j * (2 * math.pi / total_count) + len(sgen_types[i]) * (2 * math.pi / total_count) for j in - range(gen_count)], - 'load': [j * (2 * math.pi / total_count) + (len(sgen_types[i]) + gen_count) * (2 * math.pi / total_count) for j in range(load_count)] - } + if i not in patch_count_unique: + patch_count_unique[i] = {} + if 'load' not in patch_count_unique[i]: + patch_count_unique[i]['load'] = [] + patch_count_unique[i]['load'].extend( + [j * seperation_angle + sgen_count + gen_count * seperation_angle for j in range(load_count)]) if plot_sgens and len(net.sgen): sgc = create_sgen_collection(net, size=sgen_size, unique_angles=patch_count_unique, orientation=orientation) diff --git a/tutorials/distributed_slack.ipynb b/tutorials/distributed_slack.ipynb index 9aaeda03d..8b7dac59b 100644 --- a/tutorials/distributed_slack.ipynb +++ b/tutorials/distributed_slack.ipynb @@ -47,7 +47,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -167,6 +167,7 @@ " var fig = this;\n", "\n", " var canvas_div = (this.canvas_div = document.createElement('div'));\n", + " canvas_div.setAttribute('tabindex', '0');\n", " canvas_div.setAttribute(\n", " 'style',\n", " 'border: 1px solid #ddd;' +\n", @@ -177,7 +178,8 @@ " 'outline: 0;' +\n", " 'overflow: hidden;' +\n", " 'position: relative;' +\n", - " 'resize: both;'\n", + " 'resize: both;' +\n", + " 'z-index: 2;'\n", " );\n", "\n", " function on_keyboard_event_closure(name) {\n", @@ -200,7 +202,13 @@ "\n", " var canvas = (this.canvas = document.createElement('canvas'));\n", " canvas.classList.add('mpl-canvas');\n", - " canvas.setAttribute('style', 'box-sizing: content-box;');\n", + " canvas.setAttribute(\n", + " 'style',\n", + " 'box-sizing: content-box;' +\n", + " 'pointer-events: none;' +\n", + " 'position: relative;' +\n", + " 'z-index: 0;'\n", + " );\n", "\n", " this.context = canvas.getContext('2d');\n", "\n", @@ -220,7 +228,12 @@ " ));\n", " rubberband_canvas.setAttribute(\n", " 'style',\n", - " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", + " 'box-sizing: content-box;' +\n", + " 'left: 0;' +\n", + " 'pointer-events: none;' +\n", + " 'position: absolute;' +\n", + " 'top: 0;' +\n", + " 'z-index: 1;'\n", " );\n", "\n", " // Apply a ponyfill if ResizeObserver is not implemented by browser.\n", @@ -270,10 +283,10 @@ " canvas.setAttribute('width', width * fig.ratio);\n", " canvas.setAttribute('height', height * fig.ratio);\n", " }\n", - " canvas.setAttribute(\n", - " 'style',\n", - " 'width: ' + width + 'px; height: ' + height + 'px;'\n", - " );\n", + " /* This rescales the canvas back to display pixels, so that it\n", + " * appears correct on HiDPI screens. */\n", + " canvas.style.width = width + 'px';\n", + " canvas.style.height = height + 'px';\n", "\n", " rubberband_canvas.setAttribute('width', width);\n", " rubberband_canvas.setAttribute('height', height);\n", @@ -289,34 +302,53 @@ " this.resizeObserverInstance.observe(canvas_div);\n", "\n", " function on_mouse_event_closure(name) {\n", - " return function (event) {\n", - " return fig.mouse_event(event, name);\n", - " };\n", + " /* User Agent sniffing is bad, but WebKit is busted:\n", + " * https://bugs.webkit.org/show_bug.cgi?id=144526\n", + " * https://bugs.webkit.org/show_bug.cgi?id=181818\n", + " * The worst that happens here is that they get an extra browser\n", + " * selection when dragging, if this check fails to catch them.\n", + " */\n", + " var UA = navigator.userAgent;\n", + " var isWebKit = /AppleWebKit/.test(UA) && !/Chrome/.test(UA);\n", + " if(isWebKit) {\n", + " return function (event) {\n", + " /* This prevents the web browser from automatically changing to\n", + " * the text insertion cursor when the button is pressed. We\n", + " * want to control all of the cursor setting manually through\n", + " * the 'cursor' event from matplotlib */\n", + " event.preventDefault()\n", + " return fig.mouse_event(event, name);\n", + " };\n", + " } else {\n", + " return function (event) {\n", + " return fig.mouse_event(event, name);\n", + " };\n", + " }\n", " }\n", "\n", - " rubberband_canvas.addEventListener(\n", + " canvas_div.addEventListener(\n", " 'mousedown',\n", " on_mouse_event_closure('button_press')\n", " );\n", - " rubberband_canvas.addEventListener(\n", + " canvas_div.addEventListener(\n", " 'mouseup',\n", " on_mouse_event_closure('button_release')\n", " );\n", - " rubberband_canvas.addEventListener(\n", + " canvas_div.addEventListener(\n", " 'dblclick',\n", " on_mouse_event_closure('dblclick')\n", " );\n", " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband_canvas.addEventListener(\n", + " canvas_div.addEventListener(\n", " 'mousemove',\n", " on_mouse_event_closure('motion_notify')\n", " );\n", "\n", - " rubberband_canvas.addEventListener(\n", + " canvas_div.addEventListener(\n", " 'mouseenter',\n", " on_mouse_event_closure('figure_enter')\n", " );\n", - " rubberband_canvas.addEventListener(\n", + " canvas_div.addEventListener(\n", " 'mouseleave',\n", " on_mouse_event_closure('figure_leave')\n", " );\n", @@ -344,7 +376,7 @@ " };\n", "\n", " // Disable right mouse context menu.\n", - " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", + " canvas_div.addEventListener('contextmenu', function (_e) {\n", " event.preventDefault();\n", " return false;\n", " });\n", @@ -499,7 +531,7 @@ "};\n", "\n", "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", - " fig.rubberband_canvas.style.cursor = msg['cursor'];\n", + " fig.canvas_div.style.cursor = msg['cursor'];\n", "};\n", "\n", "mpl.figure.prototype.handle_message = function (fig, msg) {\n", @@ -611,30 +643,22 @@ " };\n", "};\n", "\n", - "// from https://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", - "mpl.findpos = function (e) {\n", - " //this section is from http://www.quirksmode.org/js/events_properties.html\n", - " var targ;\n", - " if (!e) {\n", - " e = window.event;\n", + "function getModifiers(event) {\n", + " var mods = [];\n", + " if (event.ctrlKey) {\n", + " mods.push('ctrl');\n", " }\n", - " if (e.target) {\n", - " targ = e.target;\n", - " } else if (e.srcElement) {\n", - " targ = e.srcElement;\n", + " if (event.altKey) {\n", + " mods.push('alt');\n", " }\n", - " if (targ.nodeType === 3) {\n", - " // defeat Safari bug\n", - " targ = targ.parentNode;\n", + " if (event.shiftKey) {\n", + " mods.push('shift');\n", " }\n", - "\n", - " // pageX,Y are the mouse positions relative to the document\n", - " var boundingRect = targ.getBoundingClientRect();\n", - " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", - " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", - "\n", - " return { x: x, y: y };\n", - "};\n", + " if (event.metaKey) {\n", + " mods.push('meta');\n", + " }\n", + " return mods;\n", + "}\n", "\n", "/*\n", " * return a copy of an object with only non-object keys\n", @@ -651,29 +675,25 @@ "}\n", "\n", "mpl.figure.prototype.mouse_event = function (event, name) {\n", - " var canvas_pos = mpl.findpos(event);\n", - "\n", " if (name === 'button_press') {\n", " this.canvas.focus();\n", " this.canvas_div.focus();\n", " }\n", "\n", - " var x = canvas_pos.x * this.ratio;\n", - " var y = canvas_pos.y * this.ratio;\n", + " // from https://stackoverflow.com/q/1114465\n", + " var boundingRect = this.canvas.getBoundingClientRect();\n", + " var x = (event.clientX - boundingRect.left) * this.ratio;\n", + " var y = (event.clientY - boundingRect.top) * this.ratio;\n", "\n", " this.send_message(name, {\n", " x: x,\n", " y: y,\n", " button: event.button,\n", " step: event.step,\n", + " modifiers: getModifiers(event),\n", " guiEvent: simpleKeys(event),\n", " });\n", "\n", - " /* This prevents the web browser from automatically changing to\n", - " * the text insertion cursor when the button is pressed. We want\n", - " * to control all of the cursor setting manually through the\n", - " * 'cursor' event from matplotlib */\n", - " event.preventDefault();\n", " return false;\n", "};\n", "\n", @@ -728,9 +748,9 @@ "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n", "// prettier-ignore\n", "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o\", \"download\"]];\n", "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", + "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\n", "\n", "mpl.default_extension = \"png\";/* global mpl */\n", "\n", @@ -1018,7 +1038,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -1044,7 +1064,7 @@ "net = nw.case9()\n", "fig = plt.figure(figsize=(4,4))\n", "ax = fig.add_subplot()\n", - "pp.plotting.simple_plot(net, plot_loads=True, plot_gens=True, load_size=2.5, gen_size=0.1, ax=ax);\n", + "pp.plotting.simple_plot(net, plot_loads=True, plot_gens=True, load_size=2.5, gen_size=2.0, ax=ax);\n", "fig.tight_layout(pad=0)" ] }, @@ -1456,7 +1476,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.8.16" } }, "nbformat": 4, From 92454140659c855e8097439c34ba30e25422c38d Mon Sep 17 00:00:00 2001 From: hzraja Date: Wed, 5 Jul 2023 15:30:39 +0200 Subject: [PATCH 22/33] fixed tutorial bug #2 --- pandapower/plotting/simple_plot.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index dea5ba1ab..88606d3d4 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -187,7 +187,6 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g sgen_count = 0 gen_count = 0 load_count = 0 - sgen_key = {} if plot_sgens and len(net.sgen): try: sgen_count = len(sgen_types[i]) From ee3aecdb8cd21981f73cba1be2d4a805bb7f98af Mon Sep 17 00:00:00 2001 From: hzraja Date: Mon, 31 Jul 2023 11:20:01 +0200 Subject: [PATCH 23/33] Fixed tutorial internal_datastructure bug --- pandapower/plotting/collections.py | 2 +- pandapower/plotting/patch_makers.py | 165 ++++--- pandapower/plotting/simple_plot.py | 1 + tutorials/internal_datastructure.ipynb | 86 ++-- tutorials/state_estimation.ipynb | 599 +++++++++++++++++++++++-- 5 files changed, 716 insertions(+), 137 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index b4da3f069..64dbbc94b 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -961,7 +961,7 @@ def create_busbar_collection(net, buses=None, infofunc=None, cmap=None, norm=Non return lc -def create_load_collection(net, loads=None, size=1., unique_angles=None, infofunc=None, orientation=None, picker=False, +def create_load_collection(net, loads=None, size=1., unique_angles={}, infofunc=None, orientation=None, picker=False, **kwargs): """ Creates a matplotlib patch collection of pandapower loads. diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 282112e18..f0932a360 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -197,16 +197,19 @@ def load_patches(node_coords, size, angles, unique_angles, **kwargs): for i in node_coords.index: node_geo = list(node_coords.loc[i]) - if "load" in unique_angles[i] and unique_angles[i]["load"] != []: - try: - angle = (unique_angles[i]["load"][0]) + (all_angles[i] or 0) - except IndexError: - continue + if len(unique_angles) != 0: + if "load" in unique_angles[i] and unique_angles[i]["load"] != []: + try: + angle = (unique_angles[i]["load"][0]) + (all_angles[i] or 0) + except IndexError: + continue + else: + angle = all_angles[i] or 0 - p2 = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) - p3 = node_geo + _rotate_dim2(np.array([0, offset + size / 2]), angle) - polys.append(RegularPolygon(p2, numVertices=3, radius=size, orientation=-angle,fc = "w",ec="k")) - lines.append((node_geo, p3)) + p2 = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + p3 = node_geo + _rotate_dim2(np.array([0, offset + size / 2]), angle) + polys.append(RegularPolygon(p2, numVertices=3, radius=size, orientation=-angle,fc = "w",ec="k")) + lines.append((node_geo, p3)) return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} @@ -241,25 +244,28 @@ def gen_patches(node_coords, size, angles, unique_angles, **kwargs): facecolors = get_color_list(facecolor, len(node_coords)) for i in node_coords.index: - node_geo = list(node_coords.loc[i]) - if "gen" in unique_angles[i] and unique_angles[i]["gen"] != []: - try: - angle = (unique_angles[i]["gen"][0]) + (all_angles[i] or 0) - except IndexError: - continue + if len(unique_angles) != 0: + node_geo = list(node_coords.loc[i]) + if "gen" in unique_angles[i] and unique_angles[i]["gen"] != []: + try: + angle = (unique_angles[i]["gen"][0]) + (all_angles[i] or 0) + except IndexError: + continue + else: + angle = all_angles[i] or 0 + + p2 = node_geo + _rotate_dim2(np.array([0, size + offset]), angle) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) + polys.append(Circle(p2, size, fc=facecolors[i], ec=edgecolors[i])) + polys.append( + Arc(p2 + np.array([-size / 6.2, -size / 2.6]), size / 2, size, theta1=65, theta2=120, + ec=edgecolors[i])) + polys.append( + Arc(p2 + np.array([size / 6.2, size / 2.6]), size / 2, size, theta1=245, theta2=300, + ec=edgecolors[i])) + lines.append((node_geo, circ_edge)) - p2 = node_geo + _rotate_dim2(np.array([0, size + offset]), angle) - circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) - polys.append(Circle(p2, size, fc=facecolors[i], ec=edgecolors[i])) - polys.append( - Arc(p2 + np.array([-size / 6.2, -size / 2.6]), size / 2, size, theta1=65, theta2=120, - ec=edgecolors[i])) - polys.append( - Arc(p2 + np.array([size / 6.2, size / 2.6]), size / 2, size, theta1=245, theta2=300, - ec=edgecolors[i])) - lines.append((node_geo, circ_edge)) return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} - gen_printed = True def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): @@ -299,60 +305,68 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): Path = mpath.Path for i in node_coords.index: - node_geo = list(node_coords.loc[i]) - if "WT" in unique_angles[i]["sgen"]: # WT patch - try: - angle = unique_angles[i]["sgen"]["WT"] + (angles[i] or 0) - except IndexError: - continue - - mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) - circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) - circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2 * size]), angle) - mid_midcirc = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) - - codes, verts = zip(*[ - (Path.MOVETO, mid_midcirc), - (Path.LINETO, circ_topedge,), - (Path.LINETO, (circ_topedge + _rotate_dim2(np.array([- blade_coord1, - blade_coord1 ]), angle)),), - (Path.LINETO, (mid_midcirc + _rotate_dim2(np.array([- blade_coord2, + blade_coord2]), angle)),), # Blade1 - (Path.CLOSEPOLY, mid_midcirc)]) - polys.append(PathPatch(mpath.Path(verts, codes), fc="k", ec="none",lw=200000000)) - polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - lines.append((node_geo, circ_edge)) + if len(unique_angles) != 0: + node_geo = list(node_coords.loc[i]) + if "WT" in unique_angles[i]["sgen"]: # WT patch + try: + angle = unique_angles[i]["sgen"]["WT"] + (angles[i] or 0) + except IndexError: + continue + else: + angle = angles[i] or 0 + + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) + circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2 * size]), angle) + mid_midcirc = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + + codes, verts = zip(*[ + (Path.MOVETO, mid_midcirc), + (Path.LINETO, circ_topedge,), + (Path.LINETO, (circ_topedge + _rotate_dim2(np.array([- blade_coord1, - blade_coord1 ]), angle)),), + (Path.LINETO, (mid_midcirc + _rotate_dim2(np.array([- blade_coord2, + blade_coord2]), angle)),), # Blade1 + (Path.CLOSEPOLY, mid_midcirc)]) + polys.append(PathPatch(mpath.Path(verts, codes), fc="k", ec="none",lw=200000000)) + polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + lines.append((node_geo, circ_edge)) - for j in range(3): - angle = j * 2 * math.pi / 3 - rotated_verts = [] - for vertex in verts: - # Calculate the vector from the center of the hub to the vertex - x_diff = vertex[0] - mid_midcirc[0] - y_diff = vertex[1] - mid_midcirc[1] + for j in range(3): + angle = j * 2 * math.pi / 3 + rotated_verts = [] + for vertex in verts: + # Calculate the vector from the center of the hub to the vertex + x_diff = vertex[0] - mid_midcirc[0] + y_diff = vertex[1] - mid_midcirc[1] - # Rotate the vector by the desired angle - rotated_x = x_diff * math.cos(angle) - y_diff * math.sin(angle) - rotated_y = x_diff * math.sin(angle) + y_diff * math.cos(angle) + # Rotate the vector by the desired angle + rotated_x = x_diff * math.cos(angle) - y_diff * math.sin(angle) + rotated_y = x_diff * math.sin(angle) + y_diff * math.cos(angle) - # Calculate the coordinates of the rotated vertex - rotated_vertex = [mid_midcirc[0] + rotated_x, mid_midcirc[1] + rotated_y] + # Calculate the coordinates of the rotated vertex + rotated_vertex = [mid_midcirc[0] + rotated_x, mid_midcirc[1] + rotated_y] - rotated_verts.append(rotated_vertex) + rotated_verts.append(rotated_vertex) - rotated_patch = PathPatch(mpath.Path(rotated_verts, codes), fc="k", ec="none") + rotated_patch = PathPatch(mpath.Path(rotated_verts, codes), fc="k", ec="none") - polys.append(rotated_patch) + polys.append(rotated_patch) - polys.append(Circle(mid_midcirc, hub_size, fc="k", ec=edgecolors[i])) # Center hub + polys.append(Circle(mid_midcirc, hub_size, fc="k", ec=edgecolors[i])) # Center hub - center_point = mid_midcirc # Define the center point of the wind turbine patch - rotation_angle = math.pi / 4 # Define the angle of rotation + center_point = mid_midcirc # Define the center point of the wind turbine patch + rotation_angle = math.pi / 4 # Define the angle of rotation if "PV" in unique_angles[i]["sgen"]: # PV patch - try: - angle = unique_angles[i]["sgen"]["PV"] + (angles[i] or 0) - except IndexError: - continue + if len(unique_angles) != 0: + + try: + angle = unique_angles[i]["sgen"]["PV"] + (angles[i] or 0) + except IndexError: + continue + else: + angle = angles[i] or 0 + mid_rect = node_geo + _rotate_dim2(np.array([0, 2*size]), angle) rect_lbottom = [mid_rect[0] - (pv_rect_size/4), mid_rect[1]] pv_patch = Rectangle((rect_lbottom), pv_rect_size/2, pv_rect_size, angle=-angle * (180 / np.pi), @@ -368,11 +382,16 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): ] triangle_patch = Polygon(triangle_points, ec="k", fc="none") polys.append(triangle_patch) + if "wye" in unique_angles[i]["sgen"]: # Generic Patch - try: - angle = unique_angles[i]["sgen"]["wye"] + (angles[i] or 0) - except IndexError: - continue + if len(unique_angles) != 0: + + try: + angle = unique_angles[i]["sgen"]["wye"] + (angles[i] or 0) + except IndexError: + continue + else: + angle = angles[i] or 0 mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index 88606d3d4..d260c12dd 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -271,3 +271,4 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g # net = nw.create_cigre_network_mv() # net = nw.mv_oberrhein() simple_plot(net, bus_size=0.4) + diff --git a/tutorials/internal_datastructure.ipynb b/tutorials/internal_datastructure.ipynb index 65ac1f301..ec9076ef4 100644 --- a/tutorials/internal_datastructure.ipynb +++ b/tutorials/internal_datastructure.ipynb @@ -37,15 +37,15 @@ "output_type": "stream", "text": [ "This pandapower network includes the following parameter tables:\n", - " - bus (7 elements)\n", - " - load (1 element)\n", - " - sgen (1 element)\n", - " - gen (1 element)\n", - " - switch (8 elements)\n", - " - shunt (1 element)\n", - " - ext_grid (1 element)\n", - " - line (4 elements)\n", - " - trafo (1 element)\n" + " - bus (7 element)\n", + " - load (1 elements)\n", + " - sgen (1 elements)\n", + " - gen (1 elements)\n", + " - switch (8 element)\n", + " - shunt (1 elements)\n", + " - ext_grid (1 elements)\n", + " - line (4 element)\n", + " - trafo (1 elements)\n" ] } ], @@ -142,7 +142,7 @@ " 0.00000000e+00]]),\n", " 'branch': array([[ 0.00000000e+00+0.j , 1.00000000e+00+0.j ,\n", " 4.95867769e-05+0.j , 1.19008264e-04+0.j ,\n", - " 5.47391104e+00+0.j , 2.50000000e+02+0.j ,\n", + " 5.47391104e+00+0.j , 0.00000000e+00+0.j ,\n", " 2.50000000e+02+0.j , 2.50000000e+02+0.j ,\n", " 1.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 1.00000000e+00+0.j , -3.60000000e+02+0.j ,\n", @@ -154,7 +154,7 @@ " 0.00000000e+00+0.j ],\n", " [ 2.00000000e+00+0.j , 3.00000000e+00+0.j ,\n", " 6.10000000e-04+0.j , 5.60000000e-04+0.j ,\n", - " 7.64035333e-02+0.j , 2.50000000e+02+0.j ,\n", + " 7.64035333e-02+0.j , 0.00000000e+00+0.j ,\n", " 2.50000000e+02+0.j , 2.50000000e+02+0.j ,\n", " 1.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 1.00000000e+00+0.j , -3.60000000e+02+0.j ,\n", @@ -166,19 +166,19 @@ " 0.00000000e+00+0.j ],\n", " [ 3.00000000e+00+0.j , 5.00000000e+00+0.j ,\n", " 5.19662500e-03+0.j , 3.25500000e-03+0.j ,\n", - " 4.17831823e-03+0.j , 2.50000000e+02+0.j ,\n", + " 4.17831823e-03+0.j , 0.00000000e+00+0.j ,\n", " 2.50000000e+02+0.j , 2.50000000e+02+0.j ,\n", " 1.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 1.00000000e+00+0.j , -3.60000000e+02+0.j ,\n", - " 3.60000000e+02+0.j , 2.40626628e-08+0.j ,\n", - " -4.43279288e-03+0.j , 2.92589721e-14+0.j ,\n", - " 9.55197900e-16+0.j , 0.00000000e+00+0.j ,\n", + " 3.60000000e+02+0.j , 2.40626638e-08+0.j ,\n", + " -4.43279288e-03+0.j , 5.75627463e-14+0.j ,\n", + " 3.11693679e-14+0.j , 0.00000000e+00+0.j ,\n", " 0.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 0.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 0.00000000e+00+0.j ],\n", " [ 4.00000000e+00+0.j , 2.00000000e+00+0.j ,\n", " 7.62500000e-04+0.j , 7.00000000e-04+0.j ,\n", - " 9.55044167e-02+0.j , 2.50000000e+02+0.j ,\n", + " 9.55044167e-02+0.j , 0.00000000e+00+0.j ,\n", " 2.50000000e+02+0.j , 2.50000000e+02+0.j ,\n", " 1.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 1.00000000e+00+0.j , -3.60000000e+02+0.j ,\n", @@ -190,7 +190,7 @@ " 0.00000000e+00+0.j ],\n", " [ 1.00000000e+00+0.j , 2.00000000e+00+0.j ,\n", " 1.63923679e-04+0.j , 4.79726336e-03+0.j ,\n", - " -1.05000908e-02-0.01399964j, 2.50000000e+02+0.j ,\n", + " -1.05000908e-02-0.01399964j, 0.00000000e+00+0.j ,\n", " 2.50000000e+02+0.j , 2.50000000e+02+0.j ,\n", " 1.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 1.00000000e+00+0.j , -3.60000000e+02+0.j ,\n", @@ -200,6 +200,8 @@ " 0.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 0.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 0.00000000e+00+0.j ]]),\n", + " 'tcsc': array([], shape=(0, 17), dtype=float64),\n", + " 'svc': array([], shape=(0, 11), dtype=float64),\n", " 'gen': array([[ 0.00000000e+00, -6.74111530e+00, -7.14688297e+00,\n", " 0.00000000e+00, 0.00000000e+00, 1.02000000e+00,\n", " 1.00000000e+00, 1.00000000e+00, 1.00000000e+09,\n", @@ -228,7 +230,19 @@ " 'gen_is': array([ True, True]),\n", " 'DLF': array([], dtype=complex128),\n", " 'buses_ord_bfs_nets': array([], dtype=float64),\n", - " 'ref_gens': array([0]),\n", + " 'svc_is': array([], dtype=bool),\n", + " 'tcsc_is': array([], dtype=bool),\n", + " 'ref_gens': array([0], dtype=int64),\n", + " 'Ybus_svc': <6x6 sparse matrix of type ''\n", + " \twith 0 stored elements in Compressed Sparse Row format>,\n", + " 'Ybus_tcsc': <6x6 sparse matrix of type ''\n", + " \twith 0 stored elements in Compressed Sparse Row format>,\n", + " 'Yf_tcsc': <0x6 sparse matrix of type ''\n", + " \twith 0 stored elements in Compressed Sparse Row format>,\n", + " 'Yt_tcsc': <0x6 sparse matrix of type ''\n", + " \twith 0 stored elements in Compressed Sparse Row format>,\n", + " 'tcsc_fb': array([], dtype=int64),\n", + " 'tcsc_tb': array([], dtype=int64),\n", " 'J': <9x9 sparse matrix of type ''\n", " \twith 41 stored elements in Compressed Sparse Row format>,\n", " 'Vm_it': None,\n", @@ -289,7 +303,7 @@ " 0.00000000e+00, 0.00000000e+00]]),\n", " 'branch': array([[ 0.00000000e+00+0.j , 1.00000000e+00+0.j ,\n", " 4.95867769e-05+0.j , 1.19008264e-04+0.j ,\n", - " 5.47391104e+00+0.j , 2.50000000e+02+0.j ,\n", + " 5.47391104e+00+0.j , 0.00000000e+00+0.j ,\n", " 2.50000000e+02+0.j , 2.50000000e+02+0.j ,\n", " 1.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 1.00000000e+00+0.j , -3.60000000e+02+0.j ,\n", @@ -301,7 +315,7 @@ " 0.00000000e+00+0.j ],\n", " [ 2.00000000e+00+0.j , 3.00000000e+00+0.j ,\n", " 6.10000000e-04+0.j , 5.60000000e-04+0.j ,\n", - " 7.64035333e-02+0.j , 2.50000000e+02+0.j ,\n", + " 7.64035333e-02+0.j , 0.00000000e+00+0.j ,\n", " 2.50000000e+02+0.j , 2.50000000e+02+0.j ,\n", " 1.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 1.00000000e+00+0.j , -3.60000000e+02+0.j ,\n", @@ -313,19 +327,19 @@ " 0.00000000e+00+0.j ],\n", " [ 3.00000000e+00+0.j , 5.00000000e+00+0.j ,\n", " 5.19662500e-03+0.j , 3.25500000e-03+0.j ,\n", - " 4.17831823e-03+0.j , 2.50000000e+02+0.j ,\n", + " 4.17831823e-03+0.j , 0.00000000e+00+0.j ,\n", " 2.50000000e+02+0.j , 2.50000000e+02+0.j ,\n", " 1.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 1.00000000e+00+0.j , -3.60000000e+02+0.j ,\n", - " 3.60000000e+02+0.j , 2.40626628e-08+0.j ,\n", - " -4.43279288e-03+0.j , 2.92589721e-14+0.j ,\n", - " 9.55197900e-16+0.j , 0.00000000e+00+0.j ,\n", + " 3.60000000e+02+0.j , 2.40626638e-08+0.j ,\n", + " -4.43279288e-03+0.j , 5.75627463e-14+0.j ,\n", + " 3.11693679e-14+0.j , 0.00000000e+00+0.j ,\n", " 0.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 0.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 0.00000000e+00+0.j ],\n", " [ 4.00000000e+00+0.j , 2.00000000e+00+0.j ,\n", " 7.62500000e-04+0.j , 7.00000000e-04+0.j ,\n", - " 9.55044167e-02+0.j , 2.50000000e+02+0.j ,\n", + " 9.55044167e-02+0.j , 0.00000000e+00+0.j ,\n", " 2.50000000e+02+0.j , 2.50000000e+02+0.j ,\n", " 1.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 1.00000000e+00+0.j , -3.60000000e+02+0.j ,\n", @@ -337,7 +351,7 @@ " 0.00000000e+00+0.j ],\n", " [ 1.00000000e+00+0.j , 2.00000000e+00+0.j ,\n", " 1.63923679e-04+0.j , 4.79726336e-03+0.j ,\n", - " -1.05000908e-02-0.01399964j, 2.50000000e+02+0.j ,\n", + " -1.05000908e-02-0.01399964j, 0.00000000e+00+0.j ,\n", " 2.50000000e+02+0.j , 2.50000000e+02+0.j ,\n", " 1.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 1.00000000e+00+0.j , -3.60000000e+02+0.j ,\n", @@ -347,18 +361,20 @@ " 0.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 0.00000000e+00+0.j , 0.00000000e+00+0.j ,\n", " 0.00000000e+00+0.j ]]),\n", + " 'svc': array([], shape=(0, 11), dtype=float64),\n", + " 'tcsc': array([], shape=(0, 17), dtype=float64),\n", " 'baseMVA': 1,\n", " 'V': array([1.02 +0.j , 1.02082934+0.00057751j,\n", " 1.02405525+0.03223318j, 1.0294512 +0.03361899j,\n", " 1.02261145+0.03485667j, 1.02945856+0.03360804j]),\n", - " 'pv': array([3], dtype=np.int64),\n", - " 'pq': array([1, 2, 4, 5], dtype=np.int64),\n", - " 'ref': array([0], dtype=np.int64),\n", + " 'pv': array([3], dtype=int64),\n", + " 'pq': array([1, 2, 4, 5], dtype=int64),\n", + " 'ref': array([0], dtype=int64),\n", " 'Sbus': array([0. +0.j , 0. +0.j , 0. +0.j , 6. +0.j , 0.8-2.9j, 0. +0.j ]),\n", " 'r_theta_kelvin_per_mw': 0.0,\n", " 'T': 20.0},\n", " 'success': True,\n", - " 'et': 2.7024675999999985,\n", + " 'et': 2.3943931000000003,\n", " 'iterations': 3}" ] }, @@ -553,7 +569,7 @@ { "data": { "text/plain": [ - "array([0, 1, 1, 2, 2, 3, 4])" + "array([0, 1, 1, 2, 2, 3, 4], dtype=int64)" ] }, "execution_count": 7, @@ -1001,15 +1017,15 @@ "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\mmilovic\\AppData\\Local\\Temp\\ipykernel_324\\1313666249.py:18: UserWarning: FixedFormatter should only be used together with FixedLocator\n", + "C:\\Users\\hraja\\AppData\\Local\\Temp\\ipykernel_22240\\1313666249.py:18: UserWarning: FixedFormatter should only be used together with FixedLocator\n", " ax.set_yticklabels(np.arange(ybus.shape[1]))\n", - "C:\\Users\\mmilovic\\AppData\\Local\\Temp\\ipykernel_324\\1313666249.py:18: UserWarning: FixedFormatter should only be used together with FixedLocator\n", + "C:\\Users\\hraja\\AppData\\Local\\Temp\\ipykernel_22240\\1313666249.py:18: UserWarning: FixedFormatter should only be used together with FixedLocator\n", " ax.set_yticklabels(np.arange(ybus.shape[1]))\n" ] }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABisAAAL4CAYAAAAK3cQrAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdeXwU5f0H8M/Obi4ChATkiuGQUwkgIiCHgggiIiLUA0st3lXBaj1b/SlWpWA9qlXBC7Fqvc+KQa5IYggQjiBEIQQIEEMghpwk2WN25vdHutMs2Rx7zew++3m/Xnn5ZLO7n+e7M8yM88w8a1JVVQUREREREREREREREZFBJKM7QEREREREREREREREkY2DFUREREREREREREREZCgOVhARERERERERERERkaE4WEFERERERERERERERIbiYAURERERERERERERERmKgxVERERERERERERERGQoDlYQEREREREREREREZGhOFhBRERERERERERERESG4mAFEREREREREREREREZioMVRERERERERERERERkKA5WEBERERERERERERGRoThYQUREREREREREREREhuJgBRERERERERERERERGYqDFUREREREREREREREZCgOVhARERERERERERERkaE4WEFERERERERERERERIbiYAURERERERERERERERmKgxVERERERERERERERGQoDlYQEREREREREREREZGhOFhBRERERERERERERESG4mAFEREREREREREREREZioMVRERERERERERERERkKA5WEBERERERERERERGRoThYQUREREREREREREREhuJgBRERERERERERERERGYqDFUREREREREREREREZCgOVhARERERERERERERkaE4WEFERERERERERERERIbiYAURERERERERERERERmKgxVERERERERERERERGQoDlYQEREREREREREREZGhOFhBRERERERERERERESG4mAFEREREREREREREREZioMVRERERERERERERERkKA5WEBERERERERERERGRoThYQUREREREREREREREhuJgBRERERERERERERERGYqDFUREREREREREREREZCgOVhARERERERERERERkaE4WEFERERERERERERERIbiYAURERERERERERERERmKgxVERERERERERERERGQoDlYQEREREREREREREZGhOFhBRERERERERERERESG4mAFEREREREREREREREZioMVRERERERERERERERkKA5WEBERERERERERERGRoThYQUREREREREREREREhuJgBRERERERERERERERGYqDFUREREREREREREREZCgOVhARERERERERERERkaE4WEFERERERERERERERIbiYAURERERERERERERERmKgxVERERERERERERERGQoDlYQEREREREREREREZGhOFhBRERERERERERERESG4mAFEREREREREREREREZioMVRERERERERERERERkKA5WEBERERERERERERGRoThYQUREREREREREREREhuJgBRERERERERERERERGYqDFUQU2Ww24OGHgZ49gbg4YMwYYN06o3tFREREREREREQUUThYQUSR7cYbgRdeAObNA156CTCbgcsvB7KyjO4ZERERERERERFRxDCpqqoa3QkiIkPk5DTcSfHss8ADDzQ8ZrUCqalA165Adrax/SMiIiIiIiIiIooQvLOCiCLXZ5813Elx++3/eyw2FrjlFmDzZqCoyLi+ERERERERERERRRAOVhBR5MrNBQYOBDp2dH989OiG/+7apXuXiIiIiIiIiIiIIhEHK4gocpWUAD16NH3c9dixY/r2h4iIiIiIiIiIKEJZjO4AEZFh6uuBmJimj8fG/u/vzbDZbCgvL/f4c/LkSY+P19TUYM6cOXjzzTeDVBAREREREREREVF44mAFEUWuuDjAZmv6uNX6v783kpubi1tvvRX5+fmora31KfKtt97C/fffj8GDB/v0eiIiIiIiIiIiIhFxGigiilw9ejRMBXU612M9e7o9vHz5cuzcudPrgQqLxQJJ+t/m9sSJE153lYiIiIiIiIiISGQcrCCiyHXuucD+/UB1tfvjW7f+7+/NGDFiBGbMmIGuXbtqj1100UX46KOPsH79euzcuROHDx9GdXU17HY7nnzySe155eXlASyCiIiIiIiIiIgo/HGwgogi19VXA04n8MYb/3vMZgNWrgTGjAFSUtyenpSUpLWfe+45rFq1Co8++qj22N///ndcd911uOSSSzBixAj07t0bHTp0gMlkwhlnnKE9j4MVRERERERERERE7jhYQUSRa8wY4JprgL/8BXjooYZBi8mTgcOHgb//vcnTGw9WlJeX4+2338a9996LefPmYezYsbj00kuRk5PjMaqwsNDttUREFF7eeecdmEwmbN++3eiutMmNN96I9u3bG90Nn506dQpdu3bFv//9b6O7ElRz587Ftddea3Q3iIgoBPBYQ1881iAKTRysIKKIcaC0Bv/31R6MXbIB5z21Dte/sQVpDy6Fes89wHvvAX/8I+BwAKtWARdd1OT1jQcrvvnmG9x66634wx/+gHfffRdr1qxBamoqpk6d2mTA4ttvv8Vzzz2n/c7BCiKi0DF9+nQkJiZ6/D6hqqoq9OjRA2PGjIGiKAb0LnK99NJL6NChA+bOnas9VlJSgj//+c+4+OKLtTsXN27c6PH1kyZNgslkavJz2WWX+dynnJwc3HXXXRg5ciSioqJgMpmafa6nbJPJhKVLl7o97+GHH8bnn3+OH3/80ed+ERFRaOOxRmjy91hDURS89tprOPfcc9G+fXt069YN06dPR3Z2ts998uZYo6qqCg899BAGDBiAuLg49O7dG7fccguOHj3q9jwea1C44WAFEUWE7/KO4/KXsvD+lqMoqbKivNaOzYdO4q7P9+LO4ddD/qUYsFqBnBxg2jSP79G5c2et/e677+IPf/gDXn31VUiShA4dOuC7775rMmDx7bffYs6cObjwwgu113KwgogodCxbtgx2ux1/+tOfmvztkUceQVlZGd544w1IEg+b9eJwOPDSSy/h1ltvhdls1h7Pz8/HM888g+LiYgwdOrTV9znzzDPx3nvvuf089NBDPvcrLS0Nb731FkwmE84666xWnz916tQm+TNnznR7zogRI3D++efj+eef97lfREQU2nisEXoCcazx4IMP4s4778TQoUPxwgsv4P7778f+/fsxceLEZmdcaE1bjzUURcHUqVOxbNkyzJ49Gy+//DKuv/56fPrppxg3bhxqamq05/JYg8INt4REJLxjlfX440e5sDs9X6ny3U/HsXzjQY9/q6+vR3FxMfbs2eN2hcKwYcO0gQqX0wcsFi1ahDlz5uDyyy/Hm2++qT3v5MmTAaqMiIj81bdvXyxatAgffvgh1q5dqz2+bds2vPbaa7jvvvswfPhwA3sYeVatWoVff/21yZQFI0eOxMmTJ7F//37cd999rb5PQkICfve737n9TJ482ed+3XnnnaiqqsL27dsxderUVp8/cODAJvlDhgxp8rxrr70WX3zxBU6dOuVz34iIKHTxWCP0+HusIcsyli9fjquvvhrvvfcebr/9djz00ENYv349ZFn2eWqpth5rbNmyBdu2bcMzzzyDv//977j11luxdOlSvPTSSyguLsb69evdns9jDQonHKwgIuH9e+sR2OX/DVTUHdmN8vQVqNn5Laq2fIqK79/GUw//EbNnz8bEiRMxdOhQJCcnIy4uDu3atcOZZ56JYcOG4d5779XeIy4uzuOVL64Bi+rqajz55JPo0qULPv74Y3Tv3l17Du+sICIKLffddx+GDRuGu+66C1arFU6nE3fccQd69+6NRYsWuT23rq4Of/jDH9C5c2d07NgRv//971FRUeH2HJPJhCeeeKJJTp8+fXDjjTdqvzscDvz1r3/FgAEDEBsbi86dO2PChAlYt25di/315nXFxcW46qqr0L59e5xxxhl44IEH4HQ63Z7z3HPPYdy4cejcuTPi4uIwcuRIfPbZZ03ey2QyYeHChfj3v/+NQYMGITY2FiNHjkRmZqbH3JtvvhndunVDTEwMhgwZgrfffrvFuly++uor9OnTB/369XN7vEOHDm5TMraFLMsB+x/zbt26IS4uzqvX1NfXw2q1tvicqVOnora2ttXlTkRE4YvHGmIdazgcDtTX16Nbt25uj3ft2hWSJHl9vODS1mON6upq7fmN9ejRAwCavAePNSicWIzuABFRsGUVlMFRXoy6/E2o+SkDzpNHPD7vqx1tf8+WBhwaH0hVVFRg165dGDVqFKKjo2G32zlYQUQUYiwWC9544w2MGzcOTz31FLp27YqdO3fiu+++Q7t27dyeu3DhQnTq1AlPPPEE8vPzsXz5chw5cgQbN25scV5hT5544gksWbIEt956K0aPHo3q6mps374dO3fubPFqura+zul0Ytq0aRgzZgyee+45rF+/Hs8//zz69euHO++8U3veSy+9hCuvvBLz5s2D3W7HRx99hGuuuQarVq3CjBkz3LIzMjLw8ccf449//CNiYmKwbNkyXHbZZcjJyUFqaioA4MSJE7jgggu0Ew5nnHEGVq9ejVtuuQXV1dVug/+eZGdn47zzzvPqs/Rk//79iI+Ph91uR7du3XDbbbfh8ccfR1RUlN/v3RbvvPMOli1bBlVVcfbZZ+P//u//8Nvf/rbJ88455xzExcVh06ZNmD17ti59IyIiffFYQ6xjjbi4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Ju+XlJSEm266CTfddBNOnTqFiy66CE888QRuvfXWFvvh6+tO9/nnnyM2NhZr1qxxu+Nv5cqVHp/vaTqI/fv3o127dtqVlR06dIDT6Wzy5Y5tYbFY0K9fPxQWFnr92ta4pqQ4/QpQvTSXL8syioqKmpzwICKiyMRjjdA/1jhx4gSApoNDAOBwOCDLss/v3dZ8VVWb5LvOOZyez2MNCiccrCCikObPAMXppg3pjmlDuqOqzgGb04nO8TEwS01vg4yLi2t14AIA/vWvf7m97uabb25zXbz9kogoPL3xxhu46aabtLmkly9fDlmW3W6179evHzIzM5u87vT/oTx58iQ6d+6s/d6+fXv0798fRUVFLfbB19d5YjabYTKZ3Pp2+PBhfPXVVx6fv3nzZuzcuRPnnXceAKCoqAhff/01LrvsMu3qyt/85jf44IMPkJeXh9TUVLfX//rrr60OFowdOxYbN270uhaX6upqxMTEuJ0QUVUVTz/9NABg2rRpPr93W3iqsaamBi+++CK6dOniNg83APz888+wWq0YN25cUPtFREThgccaoX+sMXDgQADARx99hMsuu0x7fOfOncjPz8ftt9/u83u3NV9VVXzyySe48cYbtcc//PBDAMCIESPcns9jDQonHKwgopATyAEKTxLaRQGIavV5QNOBi9mzZ2PNmjVe5blER0ejc+fOmDNnDs4++2yf3oOIiIxlt9txySWX4Nprr0V+fj6WLVuGCRMmuF2pduutt+KOO+7Ab37zG0ydOhU//vgj1qxZ0+TW+3POOQeTJk3CyJEjkZSUhO3bt+Ozzz7DwoULW+yDr6/zZMaMGXjhhRdw2WWX4be//S1KS0vx6quvon///ti9e3eT56empmLatGn44x//iJiYGCxbtgwA8Ne//lV7ztKlS/H9999jzJgxuO2223DOOeegvLwcO3fuxPr161udhmnWrFl47733sH//fu1kgItrwOGnn34CALz33nvIysoCAPzf//0fgIYTBddffz2uv/569O/fH/X19fjyyy+xadMm3H777drJDxeTyYSJEye2etLiyJEjeO+99wAA27dvd+tP7969ccMNNwAAXn31VXz11VeYOXMmevXqhZKSErz99ts4evQo3nvvvSbTRa5btw7t2rXD1KlTW8wnIqLIwGON0D/WGDlyJKZOnYp//etfqK6uxqWXXoqSkhK8/PLLiIuLw7333uv2noE+1rjxxhvx3HPP4Q9/+ANyc3MxZMgQ7Ny5E2+99RaGDBmC2bNnu70vjzUorKhERCFg//796uLFi9Vzzz1XBeDxZ/To0eqzzz6rFhYWGtbPvLw8dcSIEWqPHj3UXr16qWeccYZqNps99rdjx47q7Nmz1ffee0+trKxUFUUxrN9ERNQ2EydOVIcMGdLk8ZUrV6oA1IyMDPX2229XExMT1fbt26vz5s1TT5486fZcp9OpPvzww2qXLl3Udu3aqdOmTVMPHDig9u7dW50/f772vKefflodPXq02qlTJzUuLk4dPHiwunjxYtVut7fYx7a8bv78+Wp8fHyT1y5atEg9/X8BVqxYoQ4YMECNiYlRBw8erK5cudLj8wCoCxYsUN9//33t+SNGjFC///77JjknTpxQFyxYoKakpKhRUVFq9+7d1UsuuUR94403WqxNVVXVZrOpXbp0UZ966qkmf2vuGKFxXw8dOqRec801ap8+fdTY2Fi1Xbt26siRI9XXXnutyb64pqZGBaDOnTu31X59//33zWZPnDhRe97atWvVqVOnqt27d1ejoqLUTp06qZdeeqm6YcMGj+87ZswY9Xe/+12r+UREJAYea4T/sYaqqmpdXZ365JNPquecc44aFxenJiQkqFdccYWam5vr9rxgHGuoqqr+8ssv6s0336z27dtXjY6OVnv06KHedttt6q+//trkfXmsQeHEpKo+fJsNEVEABPsOCr20NFWUS1JSEmbPno1rrrkGkydP1m7pJSIiChcmkwkLFizAK6+8EvSsp556CitXrkRBQUGbvrzTV2lpabjiiivw448/YujQoUHLac6uXbtw3nnnYefOnTj33HN1zyciIgolPNYIPB5rULjhYAUR6co1QPHJJ5/gxx9/9PiccBigaA4HLoiISFR6nkA4deoUzjrrLPzjH//AvHnzgpbz4IMPori4GB988EHQMloyd+5cKIqCTz75xJB8IiKiUMJjjcDjsQaFGw5WEFHQiT5A0RwOXBARkUj0PIFAREREkYfHGkTEL9gmoqCI1AGKxk7/cm5PAxfl5eVYsWIFVqxYwYELIiIiIiIiIiKKWLyzgogChgMUbcM7LoiIiIiIiIiIiNxxsIKI/MIBCv9w4IKIiIiIiIiIiIiDFUTkAw5QBAcHLoiIiIiIiIiIKFJxsIIoQqiqClVVIUmST6/nAIW+9Bq48He9ICIiIiIiIiIiCgQOVhAJzOFw4Msvv8Rrr72G7Oxs2Gw2dO/eHb/97W9x5513on///i2+ngMUoSHQAxf19fX44IMP8PrrryM3NxdOpxO9e/fG/Pnzcfvtt6Nnz57BLIeIiIiIiIiIiKgJDlYQCcZqteLTTz/F66+/jm3btsFut3t8ntlsxiuvvII77rjD7XEOUIQ2fwcuDh48iMsvvxz79+/3+P4mkwlnnnkm5s2bhz/84Q9cvkREREREREREpAsOVhAJZNeuXZg1axaOHj3q8e/t2rWDLMtuAxjvvfcexowZwwGKMOTtwMXQoUMxbtw4HDlyxO3v5eXlHt9fkiQ8+eSTeOSRR2AymYJWBxEREREREREREQcriASxf/9+XHDBBaioqHB73GQyofE/87POOguTJ0/GW2+9BaDhDgun0+nxPTlAET7aMnARGxsLq9UKADj77LMxZswYvPPOO9rfT19XXBYvXoxHHnkkaH0nIiIiIiIiIiLiYAWRIGbMmIG0tDQAQFxcHOrr6wEAmzZtwsmTJ3HPPfegsLAQAPCnP/0JO3bsQGZmZpP34QBF+Gtt4EKSJKxbtw6XXHIJgIZBikcffRQLFizAjBkzsHPnzibPP3jwINcHIiIiIiIiIiIKGsnoDhCR/w4dOoTVq1cDALp3764NVIwePRrjxo3DzJkzsWHDBsTExAAAVq5ciRtvvFF7fZcuXfDss8+isLAQW7duxQMPPMAT02EsLi4Oc+bMwYcffohff/0Vn3/+OaZOnar9fejQofj666+13xctWoSnnnoK3bt3x1133aU9Pn78eACAoih444039CuAiIiIiIiIiIgiDgcriASQlpamTd8zd+5c7fH+/ftr7b59++Lqq68GAFRWVmoDFwAwadIkDlAIyjVw8eCDD2qPXX755Vi1ahUAIDo6Gn/84x+1vw0YMEBrDxs2TPuuCtfziYiIiIiIiIiIgoGDFUQCaPw9FaNGjdLa27Ztc/sOguHDh2vtHTt2aO3OnTsHuYdktC5dumjt7du3a+tMSkoKEhMTtb/l5ORo7V69eqFr164A0OyXcBMREREREREREQUCByuIwlhBQQH+9re/4fXXX9ceW79+PSZOnKj9/bPPPtP+lpeXp7W//fZbrT1nzhwdektGGjZsGPr27QsAWLduHWJjYwEARUVFqKqqAgBUVVXh5Zdf1l4zduxYnDhxAgBw/Phx3HrrrVizZg0cDofOvSciIiIiIiIiItHxC7aJwkxBQQE+/fRTfPrpp9i1a1eTvyclJeHFF1/E73//ewBATEwMHn/8ccyYMQNjxoyBzWaD2WyG0+kE0DDtz759+yBJHLsU3bPPPouHHnoIQMN6YbPZAABPPfUURowYgUceeQS7d+8GAEyZMgXnn38+li5d2uR9kpKSMHv2bFxzzTWYPHkyoqKi9CuCiIiIiIiIiIiExMEKojDQ2gAFAHTs2BHV1dUAGq6Ij4+Px/r161t835iYGKSnp2PcuHGB7jKFIKvViqlTpyIrK6vF5yUlJeH666/HsmXLtGnE2rVrh7q6Oo/P5cAFERERERERERH5i4MVRCGqLQMUo0aNwrXXXourr74adXV1GDdunDalD9D8CWYA6NGjBz7++GNceOGFweg+haiamhrccMMN+Prrrz3+PSoqCoqiaHfeAMDjjz+Ohx9+GN999x0++eQTrFq1CrW1tU1ey4ELIiIiIiIiIiLyFQcriEKItwMUffr0cfvbtm3bMGvWLJSUlHh8bWxsLMaOHYtbbrkFV199NWJiYgJcAYWL3NxcvPbaa/jPf/6D48ePe3yOyWTCo48+iieffBImk0l7vK6ujgMXREREREREREQUUBysILGdOgU8+yywdSuQkwNUVAArVwI33mh0zzT+DlCcrra2Fh9++CHefvttHDx4EJIkYejQobj99tsxa9YsnjSmJn7++WcsW7YMq1evRlVVFRITEzFjxgzceeedGDRoUIuvjYiBi7ZsRxQFePdd4IsvgNxcoLwc6NsXmDsXeOAB4L9faE5ERERERERERJ5xsILEdvhwwwnDXr2As84CNm4MicGKQA9QEIUCYQcu2rIdOXUK6NABuOAC4IorgK5dgc2bgX/9C7joIiA9HWh0dwoREREREREREbnjYAWJzWZruAq6e3dg+3Zg1CjDBis4QEGRRKiBi7ZsR+z2hr+d/mX1Tz4JLFoErFsHTJmia7eJiIiIiIiIiMIJBysochgwWMEBCiLBBi683Y7s2QMMGwb885/A3XcHvXtEREREREREROHKYnQHiETTlgGK0aNH45prruEABUWEdu3aYc6cOZgzZ06zAxfl5eVYsWIFVqxYET4DF23h+vLyLl2M7QcRERER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Rl3+Jny4Mgvvlh7y+FoOUBCJy9uBC3NcB8QNGIt2g8YjtvdwmMz/20XW2p14+PPdWPun4OzciQJhwYIFyMvL0/2K7kGDBmHXrl2oqqrCZ599hvnz5yMjI0OXAYuioiLcc889WLdundfzsAZC4ysBhw0bhjFjxqB379745JNPAnZlUUsURcH555+Pv/3tbwCAESNGIC8vD6+99prugxUrVqzA9OnTdZ0j/5NPPsG///1vfPDBBxgyZAh27dqFe++9Fz179tSt/vfeew8333wzkpOTYTabcd555+H666/Hjh07dMknzxwOB6699lqoqorlrrsidXLxxRdj165dKCsrw5tvvolrr70WW7duRdeuXYOau2PHDrz00kvYuXOnbnc3UfjS45hBj+MDvY8D9NrvG7V/D/a+XM/9NvfPwaHH/lWP/aje+8y5c+dq7aFDh2LYsGHo168fNm7ciEsuuSRgOYqiAABmzZqFP/3pTwCAc889F9nZ2XjttdeCNljx9ttvY968eQHbDnMaKAp772/9322XqqqiZtd3OLbyjzj25h9QmfkuHKcNVHCKJ6LI05apopz1NTi1ey1KP12EX165ASe/exnOuirt7/tPnMK2w+VGdJ+a0aVLF5jNZpw4ccLt8RMnTqB79+4G9coYCxcuxKpVq/D999/jzDPP1DU7Ojoa/fv3x8iRI7FkyRIMHz4cL730ki7ZO3bsQGlpKc477zxYLBZYLBZkZGTgn//8JywWC5xOpy79cOnUqRMGDhyIAwcO6JLXo0ePJid9zj77bF2nogKAI0eOYP369bj11lt1zX3wwQfx5z//GXPnzsXQoUNxww034E9/+hOWLFmiWx/69euHjIwMnDp1CkVFRcjJyYHD4cBZZ52lWx8AaNs8bg//dyLlyJEjWLduna53VQBAfHw8+vfvjwsuuAArVqyAxWLBihUrgp77ww8/oLS0FL169dK2h0eOHMH999/P/9fxgcjHGHodM+hxfGD0cUCw9vtG7N/12Jfrud82Yv8s+r5Yr/2rHvtRo/eZZ511Frp06RLwbUeXLl1gsVh03X788MMPyM/PD+i2g4MVFNbssoIDpae0361Hd6N8zStNBihiegzkAAURAfA8cHHOhMtgivrfVQCKtQanflyD4+8/6Pban49V691dakF0dDRGjhyJDRs2aI8pioINGzbo/p0JRlFV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MrEmU7NMrCnZsypqDqn6QFO7OY1NTcpIT283J6t/ukYO7tvr/HBWsi4/t3PilZWs20V3PoP5th9JbeXKlbr22mtVW1sbuc+27cjPCRMmSJIGDx6sP/7xjzrxxBNd6acpnn76aS1dujTye3V1deRn+JRsj8ejc845RxdeeKErfTTFli1b9PDDD2v//v2SpIA+PUOopsXyHjp0qK6//vqUG4SIVjTLxbZtXX755SouLm51X/hneD/i8Xh04YUX6re//W18Ootec3suUPLJT+X8ROgD+eSTj3hwctmamGViTaZmmVhTMmeNHNy33S+Xg8GgLMuS3+93ZIA8WZdfIuTEIysVtgumgUJSu+iii7RmzRqVlZVFbi2F71u9erUuueQSl3pphvfee09XXHGFnnzyycjt4MGDkqSDBw9G7vvrX/+q//f//p927drlco+T249//GM9+OCDkeX6zLPPRB5rubzvvvtu3XnnnS72NPk9/fTT+vvf/97lfmTTpk268847tXXrVpd6is5YlqW8vDxZlkU++eSnYB/IJ598d/cBpnJy2ZqYZWJNpmaZWJOpWSbW5GSWiTWZlsU0UEhqs2bN0vLly6N67umnn6433ngjzj0y1969e3XkkUeqoaGhy+dmZWVp165d6tOnjwM9M9P111+vBx98MPK7Jy1DvoGHy9q3U5JH0qe77gceeEDXXXed0100xjvvvKPp06dH9Vyv16tDhw4pPT02cz3iU7GYBsrJI0nIJ5/8xOoD+eST3/N8poHqmJPr1sQsE2syNcvEmkzNMrEmJ7NMrCkZsrrzGcyZFUhqzz77bKs3xl/+8hctWLBAffv21dy5cyP3e71ePfPMM+29BKI0ZMgQ/eQnP4n8fsIJJ+iBBx7Qcccdp/vvv1/jxo2LPHb77bczUNFLt9xyS6sd+BNPPKHBsy5V+vAJ+kaLs4TGjBmja665xo0uGuPEE0/UCSecEPl91qxZkf3IZZddppycnMhjCxYsYKAigbl9RCn55KdyfiL0gXzyyUc8OLlsTcwysSZTs0ysydQsE2tyMsvEmkzKYrACSW306NG66KKLIr//6U9/0l//+lfV1tZq9+7dkfu/9a1vadiwYW500Sg/+clPdOSRR0qS1qxZo6OPPlrr16/XYYcdps2bN0uSJk2axJfnMTB06FDddtttkd8ff/wJ9T9mpoZffr+K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ALiKwQoAAAAAAAAAAOAqBisAAAAAAAAAAICrGKwAAAAAAAAAAACuYrACAAAAAAAAAAC4isEKAAAAAAAAAADgKgYrAAAAAAAAAACAqxisAAAAAAAAAAAArmKwAgAAAAAAAAAAuIrBCgAAAAAAAAAA4CoGKwAAAAAAAAAAgKsYrAAAAAAAAAAAAK5isAIAAAAAAAAAALiKwQoAAAAAAAAAAOAqBisAAAAAAAAAAICrGKwAAAAAAAAAAACuYrACAAAAAAAAAAC4isEKAAAAAAAAAADgKgYrAAAAAAAAAACAqxisAAAAAAAAAAAArmKwAgAAAAAAAAAAuIrBCgAAAAAAAAAA4CoGKwAAAAAAAAAAgKsYrAAAAAAAAAAAAK5isAIAAAAAAAAAALiKwQoAAAAAAAAAAOAqBisAAAAAAAAAAICrGKwAAAAAAAAAAACuYrACAAAAAAAAAAC4isEKAAAAAAAAAADgKgYrAAAAAAAAAACAqxisAAAAAAAAAAAArmKwAgAAAAAAAAAAuIrBCgAAAAAAAAAA4CoGKwAAAAAAAAAAgKsYrAAAAAAAAAAAAK5isAIAAAAAAAAAALjq/wOVOWAaybfw6AAAAABJRU5ErkJggg==\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAABioAAAL4CAYAAADlH68VAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy88F64QAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdeXwTZf4H8E8mSQ9KKS03pRxyCuVQ8OAQCgp4IYor3rf7WxUVdHW9lVURddX1QHRBxXt1UUHFAkUKLVChgOUollqgQC2FUntSaJLJzO8PNrMNPUiaZCZ58nm/Xn35NCT5PN+Z6cyYZ+aJSVVVFURERERERERERERERAaQjO4AERERERERERERERGFLw5UEBERERERERERERGRYThQQUREREREREREREREhuFABRERERERERERERERGYYDFUREREREREREREREZBgOVBARERERERERERERkWE4UEFERERERERERERERIbhQAURERERERERERERERmGAxVERERERERERERERGQYDlQQEREREREREREREZFhOFBBRERERERERERERESG4UAFEREREREREREREREZhgMVRERERERERERERERkGA5UEBERERERERERERGRYThQQUREREREREREREREhuFABRERERERERERERERGYYDFUREREREREREREREZBgOVBARERERERERERERkWE4UEFERERERERERERERIbhQAURERERERERERERERmGAxVERERERERERERERGQYDlQQEREREREREREREZFhOFBBRERERERERERERESG4UAFEREREREREREREREZhgMVRERERERERERERERkGA5UEBERERERERERERGRYThQQUREREREREREREREhuFABRERERERERERERERGYYDFUREREREREREREREZBgOVBARERERERERERERkWE4UEFERERERERERERERIbhQAURERERERERERERERmGAxVERERERERERERERGQYDlQQEREREREREREREZFhOFBBRERERERERERERESG4UAFEREREREREREREREZhgMVRERERERERERERERkGA5UEBERERERERERERGRYThQQUREREREREREREREhuFABRERERERERERERERGYYDFUREREREREREREREZBgOVBARERERERERERERkWE4UEFERERERERERERERIbhQAURERERERERERERERmGAxVERERERERERERERGQYDlQQEREREREREREREZFhOFBBRERERERERERERESG4UAFEREREREREREREREZhgMVRERERERERERERERkGA5UEBERERERERERERGRYThQQUREREREREREREREhuFABRERERERERERERERGYYDFUREREREREREREREZBgOVBARERERERERERERkWE4UEFERERERERERERERIbhQAURERERERERERERERmGAxVERERERERERERERGQYDlQQEREREREREREREZFhOFBBRERERERERERERESG4UAFEREREREREREREREZhgMVRERERERERERERERkGA5UEBERERERERERERGRYThQQUREREREREREREREhuFABRERERERERERERERGYYDFUREREREREREREREZBgOVBARERERERERERERkWE4UEFERERERERERERERIbhQAURERERERERERERERmGAxVEFHZyc3OxZs0ao7tBRERERERERERE4EAFEYWZLVu2YPjw4ZgwYQLefvtto7tDREREREREREQU9kyqqqpGd4KISA+qqmL06NH4+eefAQBt2rTBb7/9hk6dOhncMyIiIiIiIiIiovDFOyqIKGz8+9//1gYpAKC6uhrPP/ooMGsW0LUrEBUFDBsGfPmlYX0kIiIiIiIiIiIKN7yjgojCQm1tLfr374/i4mIAQGRkJGw2G1YCmBAbC8s//gH06wd88QXw/vvA558DN9xgbKeJiIiIiIiIiIjCAAcqiCgsPPPMM3j++ecBAJdddhnGjx+P1Q8/jFQAf+/fH8/k5cFkMp188qRJwK5dwMGDgNlsXKeJiIiIiIiIiIjCAAcqiEh4Bw4cwIABA1BXVweLxYJdu3ahZ8+eWNqhAy6prkY8gC+++grTp08/+YJ///vk3RQbNgCjRhnadyIiIiIiIiIiItHxOyqISHh/+9vfUFdXBwCYOXMm+vXrh4iICEzs0gV5AJwAHnnkEZw4ceLkC4YMOfnf3FxD+ktERERERERERBROLEZ3gIgokNatW4f//Oc/2u9ffvklvvvuOwBA2oEDKP/v4wcPHsSrr76Kp59+GkhIOPngH3+0KNNut6O8vLzBT21tLSZPnow+ffr4UhIREREREREREZFQeEcFEQlt2bJlbr8XFxdjz5492LNnDxwOB9RmngvXd1b8lyzLWLJkCV599VU88cQTuPvuuzF9+nRceOGFOOuss9CjRw/ExsYiMjISXbp0waBBg3DBBRdg6tSpuP3223Hfffdh3LhxsNlsAaqWiIi8dfnll6Nt27YoKipq8G/l5eXo0qULRo8ejQ8//BAmkwlbtmwxoJfemz17NkwmE8rKyozuSovdcccduPjii90ee+ONNzBt2jT06tULJpMJKSkpjb72o48+gslkavTn8OHDLe7TU089hcsvvxyJiYkwmUy47bbbGn2ea/mf+hMVFeX2vIqKCrRt2xZLly5tcZ+IiCi48VwjePlyrgEAa9aswcSJE9GxY0e0bt0aQ4YMwVtvvQWn09niPnl6rgEA33zzDUaPHo2EhAS0bdsW5557Lj799FO35/Bcg0IJ76ggIqHdeOONWLFiBYqLi7XHKisr4XQ6UQ6gk9mMdm3bonXr1njggQdOPqH8v/dZuO6s+K+nnnoKL7/8sk/9OXToEH7//Xf07t3bp/chIiL/eP/995GcnIy77roLK1eudPu3++67DzU1Nfj444+xfv16g3oYnnJycvDxxx9j06ZNbo+/9957iImJwYQJE/DDDz+c9n0WLVqEAQMGuD3Wrl27Fvfrn//8J4YMGYIrrrgCH3744Wmfv2LFCsTFxWm/S5L7dWLx8fF48MEH8cgjj+DSSy9FREREi/tGRETBiecawcnXc42ffvoJkydPxtixY7Fw4ULExMTg+++/x8yZM7F37168+eabLeqXp+caH374Ie68805cffXVeOqpp2AymfDxxx/jlltuQVlZGR588EEAPNeg0MKBCiIS2pAhQ7B9+3a3x7p164bi4mLsbdUKN0oSyg4fBiz1doc7d578b3Ky2+t2uh5vhMViQevWrVFZWYmEhASMHDkS7du3R2xsLL7//nsUFxdrV1WUl5dzoIKIKEh07twZ8+fPx7XXXot//etf+Mtf/gIAWLJkCf79739j/vz56NOnDz880NlLL72Ec889FyNGjHB7/Ndff9U+7E8+5TjdmOTk5Abv4Yuamhot/9QrFhszfPhwtG/fvtnn3H333XjhhRfw9ddf44YbbvBLP4mIKHjwXCM4+Xqu8dFHH8FqtWLZsmWIiYkBAFx00UXIz8/HRx991OKBCk/PNT788EP06NED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fBKJiYm49957tefcfPPNuOmmm3Dvvffi6quvxoEDB/DKK6+gQ4cObu81ZcoUJCcnY8SIEejQoQMOHDiAN954Az169EDfvn2b7ENLX9eYiRMnIiIiAtdffz3+9re/oa6uDu+++y4qKioafX67du1wzz334ODBg+jXrx9SU1OxcOFC3HPPPejevTsA4LrrrsPnn3+OSy+9FDNnzsS5554Lq9WK33//HWvWrMHUqVNx1VVXNdmnlJQUqKqKTZs2YdKkSW7/tmXLFuzfvx8AUF1dDVVV8fXXXwM4eQWh60rNiy66CGPHjsWQIUPQpk0b7Ny5E6+88gpMJlODeaNnz56Nv//971izZg1SUlKaXV4ZGRk4evQoAMDpdOLAgQNa/rhx47R1PHToUNx0000488wztekt/vGPf6Bz587429/+1uB9N27ciHbt2mHw4MHN5hMRkfh4rhEa5xoPPvggHnjgAUyZMgV/+ctf0KpVK6xevRqvvfYaLrroIgwdOlR7T3+fa0RGRuLee+/F66+/jltuuQXXXnstzGYzli5dii+++AJ33nmn29TVAM81KEQY9jXeREQBUltbqy5evFidPn262qpVKxWAxz/du3dXr7zySvXVV19Vv/76azU9PV3dvn27WlRUpBYVFWnPGz9+fJP5mzZt0p4XGxur5ufnq6qqqm3atFEBqP369dNrURARkZfGjRunDho0qMHjixYtUgGoaWlp6s0336y2bdtWjY6OVi+99FK1oKDA7bmKoqivvPKKesYZZ6hRUVHqiBEj1PT0dHXcuHHquHHjtOe99tpr6qhRo9T27durERERavfu3dU777xT3b9/f7N99OR1zz77rApAPXr0aKN1FBYWao/98MMP6tChQ9WoqCg1MTFRfeSRR9Tly5erANQ1a9Y0WDZr165VR4wYoUZGRqpdunRRn3jiCdXhcLjlOBwO9dVXX9Xet3Xr1uqAAQPUv/zlLw2W16mcTqfas2dP9d57723wb7feemuTx/BFixZpz5s1a5Y6cOBANTY2VrVYLGrXrl3Vm266STsm1/fXv/5VNZlMal5eXrP9ci2DpvLrL6vrrrtO7dOnjxoTE6NarVa1R48e6t13360eOnSowXsqiqL26NFDvf/++0+bT0REoY/nGmKca6iqqn7zzTfqmDFj1Pbt26sxMTHqoEGD1Oeff149duyY2/MCca7hdDrVhQsXqiNGjFDbtm2rtmnTRj3rrLPUefPmqXa73e09ea5BocKkqqrq/+EPIiJ9HT9+HKmpqVi8eDGWLVuG48ePN3iOFN0GrfqNhNSqLU4U/AxLQiIcRw9ArjjU8LmShHHjxuGaa67BtGnT0KlTJzidTlitVqiqiqioKBQWFjb4ojPXd1IkJyfjo48+wtSpU1FVVYU1a9Zg8uTJ2L9/P9q3b69dIUFERBQqUlJSUFZWhtzc3IBnvfbaa5gzZw6Ki4vd7koMhHPPPRc9evTA4sWLA5rTlNWrV2PSpEnYtWsXBgwYYEgfiIiIggHPNQKD5xoUKjhQQUQhy5PBiXbt2uHyK6ZiE/rjeLv+MJndZ7xTVRVKWSEuiirEhlXLUFBQ0OA96g9aPP7446iqqoLZbEa/fv2Qnp6uDVbUH6RYsWIFYmNjcfjwYUyYMAFVVVWIj4/Hrl27IEkSHA6HoV/mSURE5C09Pzyoq6vDmWeeiRkzZuDhhx8OWE51dTU6dOiAbdu24cwzzwxYTnPGjx+PPn36NDlXNxERUbjguUZg8FyDQgW/o4KIQoqngxPTpk3DNddcg5SUFFitVuwpPYY/f7IFhWW1bs9tE2XFK7P+hEsGd4Gqvobt27dj8eLFWLx4sTZooSgK1qxZgzVr1mivi4iIQHl5OSZMmID09HQcPHiwwSBFXV0dFEXB/PnzcdtttyE/P197v5qaGr9+QSgREZFIoqKi8OmnnyInJyegOW3atIHNZjv9EwOkoqIC48aNc5t3nIiIiAKP5xpEwYd3VBBR0Gvp4MSpFEXFmvxSrM0/CllRMDixLaYO64qYyIZjtqqqNjpoUZ/JZIIkSXA6nQBOnoB0794dFRUVKC8vx4kTJ5qsad++fejVq5c3i4GIiIiIiIiIiEhIHKggoqDkr8EJf6g/aPHGG2802hdvJCQkoKSkBBEREX7qIRERERERERERUeji1E9EFDSCaXCiPpPJhGHDhmHYsGGIiIjA7NmzT/uamJgYdOnSBX369EHXrl2RkJCAdu3aISEhAVOmTOEgBRERERERERER0X/xjgoiMlSwDk40pa6uDj/88IP25dgVFRXYtGkTVq9ejcLCwgbPr/9F3NOmTUOnTp0M6DUREREREREREVHw4kAFEeku1AYnPOHJd1pIkoSxY8di+vTpHLQgIiIiIiIiIiL6Lw5UEJEuRBycaAoHLYiIiIiIiIiIiDzHgQoiCphwGpxoCgctiIiIiIiIiIiImseBCiLyKw5ONI2DFkRERERERERERA1xoIKIfMbBCe9x0IKIiIiIiIiIiOgkDlQQUYtwcMJ/OGhBREREREREREThjAMVROQxDk4EHgctiIiIiIiIiIgo3HCggkhwiqIgPT0dW7Zsgd1uR1JSEq666iq0bdvWo9dzcMI4gRy0cDgcWL58OXbu3AlFUdCnTx9ceeWViI6O9ncZREREREREREREzeJABZGAnE4nMjMz8Z///AdLlizBkSNH3P69VatWuP322/Hyyy8jJiamwes5OBF8/DVooaoq5s2bh5deegmHDh1y+7eYmBiMHz8et99+OyZNmoTWrVsHrB4iIiIiIiIiIiIXDlQQCcTpdOLNN9/EW2+9hQMHDpz2+eeeey5Wr16N1q1bc3AihLR00EJVVTzwwAOYN2/eaTNat26N22+/HbNnz0ZCQkIgyiAiIiIiIiIiIgLAgQoiYciyjOuvvx5ff/11s88bP348Nm7ciBMnTgAAUlJS0LFjRw5OhChvBi26d++OTz75RHt83Lhx2LJlC2pra5t8/wEDBmDNmjXo3LlzQPpPRERERERERETEgQoiQTz11FOYM2dOg8fHjx+PkpIS7N69G8DJD60XLVqEe+65p9GBCYCDE6HKk0ELl3feeQcvvPACSkpKAADt27dHSkoKvvnmG5x6WBg9ejTWrVsHk8kU0P4TEREREREREVF44kAFkQCOHTuGrl27oqamBpIkQVVVqKqKbt26obCwEJIk4cEHH8Rbb70FALjyyishSRK+/fZb7T04OCGW5gYtOnfujMcffxwzZ84EAIwaNQqpqamIi4vD9ddfjy+//BIAkJCQgPLycgBAZmYmLrjgAv0LISIiIiIiIiIi4UlGd4CIfLd48WLU1NQAAC6//HLtivhLL70UFosFkiTh1VdfRdeuXQEA33//PW677Tbt9ZdffjlKSkqwYMECTJw4kYMUAjCZTBg2bBjmzJmD/Px8vPLKK9q/3X777Xj//fe13//1r38hLi4OADB16lTt8YkTJ2rthQsX6tBrIiIiIiIiIiIKRxyoIBLAr7/+qrXrf7hcV1enta1WK6666ioAgKIo2Ldvn/ZvPXv25OCEwEwmE3r37q39brFYtG3mzDPPRHJysvZv9beZYcOGae362xgREREREREREZE/caCCKMQdP34c+fn52u8dOnRAVFQUAOC7777DsWPHtH+TpP/9yf/0009ae8iQITr0lIw0ePBgrf3ll19qd93U3yYA4PPPP9fa9beL0tJSHDlyJMC9JCIiIiIiIiKicMSBCqIQdPz4cXz99de49tpr0aFDB/zwww/avy1YsADXX389AKCqqgp//vOfUVdXB1mWsXTpUu15y5cvBwC0bt0a1113na79J/317dsX48ePBwAUFBSgbdu2AIBdu3YhPz8fqqri7bff1gawevXqhf3792uvLyoqQteuXTF+/Hi8++67HLQgIiIiIiIiIiK/4ZdpE4WI48ePIzU1FYsXL8ayZctw/PjxRp9nsViwcOFC3HPPPdo0Pp07d0ZSUhI2b97c4PlPP/00nnvuuYD2nYLD6tWrMXHiRJy62+/Zsydat26N3Nxc7bFXX30V8+bNcxusqE+SJIwdOxbTp0/HtGnT0KlTp0B2nYiIiIiIiIiIBMaBChJKXV0dXnrpJbRv3x4zZsyAyWQyuks+8WRwol27drjqqqtQWVmJr7/+GsDJD5HPP/98ZGdnQ5blJt//xhtvxMcffwyz2RywGii4/Otf/8I999zTYLCivhEjRuC3335DdXU1AGDgwIGYOnUqvv76axQUFDR4voiDFitXrkRqaioeeeQRdOvWzejuEBEREREREREJjQMVJJSZM2firbfeAgC8//77uPPOOw3ukfe8GZyYPn06UlJSYLVaYbfbcdVVVyE1NfW0GQMHDsTMmTNx1113NfiOAhLfmjVrMHfuXKxateq0z+3VqxcyMjKQlJQEVVWxfft2LF68GIsXLxZ20GL37t0YPHgwZFnGsGHDsGXLFg7mEREREREREREFED+hJGH8+uuveOedd7Tfn3jiCe2K8GB36ndOXHPNNfjPf/7jNkjRrl073HXXXUhLS0NJSQkWLlyIiRMnwmq1AgAiIiKwdOlSPPfcc+jYsWODjDPOOAOPP/44tm7ditzcXPzf//0fBynC1Pjx45GWloZ9+/Zh3rx5GDFiRIPnREVF4fbbb8fPP/+MpKQkAIDJZMKwYcMwZ84c5OfnIycnB0888QT69u2rvU5RFKxduxb33ntvyH6nxUMPPaTdibRt2zZ8+OGHBveITmf+/Pno1asXoqKiMHz4cKxbt0637MzMTEyZ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V7u67bWtqaamRnv27HF124vWtGTJEm3YsEGO47i+7UnS1q1bVV5eHnsvurntNTc3x7a9lpaWlG170b73RV+2vWXLen99iqh4297GjRv7/Np91d00k7W1te1uTz75pCzL0hVXXJHSfjmOo5qaGteOhjUty8SaTM0ysSZTs0ysye0st7D8eo6LaQNABmD/h3RhWVa7i2mvWrVKl112mVavXh27NsWYMWM0b968Li+mHQwGFQwGYz/X19erqKhI+/fvV0FBQezoTr/f365t27Ysy4q1fT6ffD6fmpubtWLFCp177rmSFLu/tbVVfr8/1g4EArIsK9aWIke4tm3n5OTEjl7NycmR4zgKhUKxtuM4CgQC7dotLS168803de6558qyrNhZDvHqSKSmeO3OagqFQnrjjTd0zjnnxM4q6WtNbduhUKjLmsLhsN544w2dffbZysvLS0pNPVlPlmXpjTfe0NSpU9WvX7+k1NST9RQdqJkyZYpyc3Nd3fYcx1FLS4tWrlypqVOnyu/3u7rtWZalw4cPa+XKlTrnnHMkydVtL9q2bVsrVqzQ1KlTFQgEXNv2onVE18HZZ58tn8/n2rbX2T4weoaBG9tetB0MBrV8+fLYPtCtbS/atm1b5eXl7faByd721tcc1OcffrPjB1qCXrxumk4+dmCvt713du7XnEeW9yl/wvBBnW57Bw4cUGFhYdpcZPrIvzU6M2fOHDU0NGjRokUJv25vLqZ95LaVSiZmmViTqVkm1mRqlok1JTtrfc1Bfe53vR/gf/G6aZo4Kr9PfZAyd/lJyV+GiX4GM1ABABmA/R/SxZFfHjz44IO64YYb5PN9fJJmKBSSz+dTUVGRtm/fntDr9ubLAwAA3OL1lx6pzE+3z+DuBip2796t4447Tk899ZSuuuqquK+T7IMiUj3gmYpBXGqiJmqipmysqfKDxj59Zj73g7M1aXRhWtXk9npK1gES0b4nelAEUz8BAIBe+/rXv661a9eqoqIidhs5cqRuuukmvfLKK671w3Ec7dixw7NTXcknn3zv8tOhD+Rndz7c9dRTT2nw4MGaO3dul89L1jSTFRUVchzHlSnkduzY4coUcjt27NCOHTuoqZc1OY6jd999V0uWLElpTdXV1XIcR6+//rp27dpFTb2YvnDPnj1atGiRHMdxZUrGdevWyXFSOxWtiTXt27dPS5Ys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", "text/plain": [ "
" ] @@ -1048,7 +1064,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/tutorials/state_estimation.ipynb b/tutorials/state_estimation.ipynb index e5269a6ff..97e84a413 100644 --- a/tutorials/state_estimation.ipynb +++ b/tutorials/state_estimation.ipynb @@ -18,9 +18,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "This pandapower network includes the following parameter tables:\n", + " - bus (3 element)\n", + " - ext_grid (1 elements)\n", + " - line (3 element)" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "import pandapower as pp\n", "\n", @@ -62,11 +76,77 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namemeasurement_typeelement_typeelementvaluestd_devside
0Nonevbus11.0060.004None
1Nonevbus20.9680.004None
\n", + "
" + ], + "text/plain": [ + " name measurement_type element_type element value std_dev side\n", + "0 None v bus 1 1.006 0.004 None\n", + "1 None v bus 2 0.968 0.004 None" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "pp.create_measurement(net, \"v\", \"bus\", 1.006, .004, element=b1) # V at bus 1\n", "pp.create_measurement(net, \"v\", \"bus\", 0.968, .004, element=b2) # V at bus 2\n", @@ -82,9 +162,97 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namemeasurement_typeelement_typeelementvaluestd_devside
0Nonevbus11.0060.004None
1Nonevbus20.9680.004None
2Nonepbus20.5010.010None
3Noneqbus20.2860.010None
\n", + "
" + ], + "text/plain": [ + " name measurement_type element_type element value std_dev side\n", + "0 None v bus 1 1.006 0.004 None\n", + "1 None v bus 2 0.968 0.004 None\n", + "2 None p bus 2 0.501 0.010 None\n", + "3 None q bus 2 0.286 0.010 None" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "pp.create_measurement(net, \"p\", \"bus\", 0.501, 0.01, element=b2) # P at bus 2\n", "pp.create_measurement(net, \"q\", \"bus\", 0.286, 0.01, element=b2) # Q at bus 2\n", @@ -100,9 +268,141 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namemeasurement_typeelement_typeelementvaluestd_devside
0Nonevbus11.0060.004None
1Nonevbus20.9680.004None
2Nonepbus20.5010.010None
3Noneqbus20.2860.010None
4Nonepline00.8880.0081
5Nonepline11.1730.0081
6Noneqline00.5680.0081
7Noneqline10.6630.0081
\n", + "
" + ], + "text/plain": [ + " name measurement_type element_type element value std_dev side\n", + "0 None v bus 1 1.006 0.004 None\n", + "1 None v bus 2 0.968 0.004 None\n", + "2 None p bus 2 0.501 0.010 None\n", + "3 None q bus 2 0.286 0.010 None\n", + "4 None p line 0 0.888 0.008 1\n", + "5 None p line 1 1.173 0.008 1\n", + "6 None q line 0 0.568 0.008 1\n", + "7 None q line 1 0.663 0.008 1" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "pp.create_measurement(net, \"p\", \"line\", 0.888, 0.008, element=l1, side=b1) # Pline (bus 1 -> bus 2) at bus 1\n", "pp.create_measurement(net, \"p\", \"line\", 1.173, 0.008, element=l2, side=b1) # Pline (bus 1 -> bus 3) at bus 1\n", @@ -129,11 +429,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], "source": [ "from pandapower.estimation import estimate\n", "\n", @@ -154,9 +462,152 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namemeasurement_typeelement_typeelementvaluestd_devside
0Nonevbus11.0060.004None
1Nonevbus20.9680.004None
2Nonepbus20.5010.010None
3Noneqbus20.2860.010None
4Nonepline00.8880.0081
5Nonepline11.1730.0081
6Noneqline00.5680.0081
7Noneqline10.6630.0081
8Nonepline01.0000.0083
\n", + "
" + ], + "text/plain": [ + " name measurement_type element_type element value std_dev side\n", + "0 None v bus 1 1.006 0.004 None\n", + "1 None v bus 2 0.968 0.004 None\n", + "2 None p bus 2 0.501 0.010 None\n", + "3 None q bus 2 0.286 0.010 None\n", + "4 None p line 0 0.888 0.008 1\n", + "5 None p line 1 1.173 0.008 1\n", + "6 None q line 0 0.568 0.008 1\n", + "7 None q line 1 0.663 0.008 1\n", + "8 None p line 0 1.000 0.008 3" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "pp.create_measurement(net, \"p\", \"line\", 1.0, 0.008, element=l1, side=b3) # Pline (bus 1 -> bus 2) at bus 3\n", "net.measurement" @@ -171,9 +622,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], "source": [ "from pandapower.estimation import remove_bad_data\n", "import numpy as np\n", @@ -200,20 +659,48 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": { "scrolled": false }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "1 0.999629\n", + "2 0.974156\n", + "3 0.943890\n", + "Name: vm_pu, dtype: float64" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "net.res_bus_est.vm_pu" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "1 0.000000\n", + "2 -1.247547\n", + "3 -2.745717\n", + "Name: va_degree, dtype: float64" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "net.res_bus_est.va_degree" ] @@ -228,18 +715,46 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "1 -2.064016\n", + "2 0.495975\n", + "3 1.514221\n", + "Name: p_mw, dtype: float64" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "net.res_bus_est.p_mw" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "1 -1.226440\n", + "2 0.297750\n", + "3 0.787529\n", + "Name: q_mvar, dtype: float64" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "net.res_bus_est.q_mvar" ] @@ -253,18 +768,46 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "0 0.892992\n", + "1 1.171024\n", + "2 0.385912\n", + "Name: p_from_mw, dtype: float64" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "net.res_line_est.p_from_mw" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "0 0.558822\n", + "1 0.667619\n", + "2 0.227756\n", + "Name: q_from_mvar, dtype: float64" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "net.res_line_est.q_from_mvar" ] @@ -281,7 +824,7 @@ "metadata": { "anaconda-cloud": {}, "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -295,7 +838,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.12" + "version": "3.8.16" } }, "nbformat": 4, From f5a504371252b9ed21c6d795e70c9475954bcde2 Mon Sep 17 00:00:00 2001 From: hzraja Date: Tue, 1 Aug 2023 09:53:40 +0200 Subject: [PATCH 24/33] fixed tutorial distributed_slack bug --- pandapower/plotting/patch_makers.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index f0932a360..8aea3050a 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -203,6 +203,8 @@ def load_patches(node_coords, size, angles, unique_angles, **kwargs): angle = (unique_angles[i]["load"][0]) + (all_angles[i] or 0) except IndexError: continue + else: + continue else: angle = all_angles[i] or 0 @@ -251,6 +253,8 @@ def gen_patches(node_coords, size, angles, unique_angles, **kwargs): angle = (unique_angles[i]["gen"][0]) + (all_angles[i] or 0) except IndexError: continue + else: + continue else: angle = all_angles[i] or 0 @@ -312,6 +316,8 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): angle = unique_angles[i]["sgen"]["WT"] + (angles[i] or 0) except IndexError: continue + else: + continue else: angle = angles[i] or 0 From 555ebf14a47e1294e95b8c3594ef155018a31b2a Mon Sep 17 00:00:00 2001 From: hzraja Date: Mon, 7 Aug 2023 10:15:32 +0200 Subject: [PATCH 25/33] Fixed -sgen patches not appearing in some cases --- pandapower/plotting/collections.py | 1 - pandapower/plotting/patch_makers.py | 127 +++++++++++++--------------- pandapower/plotting/simple_plot.py | 31 +++---- 3 files changed, 74 insertions(+), 85 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index 64dbbc94b..03c10895a 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -1163,7 +1163,6 @@ def create_ext_grid_collection(net, size=1., infofunc=None, orientation=0, picke infos = [infofunc(ext_grid_idx) for ext_grid_idx in ext_grids] if infofunc is not None else [] node_coords = net.bus_geodata.loc[ext_grid_buses, ["x", "y"]].values - sgen_type = net.sgen.type color = kwargs.pop("color", "k") ext_grid_pc, ext_grid_lc = _create_node_element_collection( diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 8aea3050a..cebfb3549 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -5,8 +5,7 @@ import sys import numpy as np try: - from matplotlib.patches import RegularPolygon, Arc, Circle, Rectangle, Ellipse, Wedge, PathPatch, Polygon - from matplotlib import text + from matplotlib.patches import RegularPolygon, Arc, Circle, Rectangle, Ellipse, PathPatch, Polygon import matplotlib.path as mpath # import matplotlib.transforms as transforms import math @@ -246,8 +245,8 @@ def gen_patches(node_coords, size, angles, unique_angles, **kwargs): facecolors = get_color_list(facecolor, len(node_coords)) for i in node_coords.index: + node_geo = list(node_coords.loc[i]) if len(unique_angles) != 0: - node_geo = list(node_coords.loc[i]) if "gen" in unique_angles[i] and unique_angles[i]["gen"] != []: try: angle = (unique_angles[i]["gen"][0]) + (all_angles[i] or 0) @@ -309,96 +308,83 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): Path = mpath.Path for i in node_coords.index: - if len(unique_angles) != 0: - node_geo = list(node_coords.loc[i]) - if "WT" in unique_angles[i]["sgen"]: # WT patch - try: - angle = unique_angles[i]["sgen"]["WT"] + (angles[i] or 0) - except IndexError: - continue - else: - continue - else: - angle = angles[i] or 0 - - mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) - circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) - circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2 * size]), angle) - mid_midcirc = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) - - codes, verts = zip(*[ - (Path.MOVETO, mid_midcirc), - (Path.LINETO, circ_topedge,), - (Path.LINETO, (circ_topedge + _rotate_dim2(np.array([- blade_coord1, - blade_coord1 ]), angle)),), - (Path.LINETO, (mid_midcirc + _rotate_dim2(np.array([- blade_coord2, + blade_coord2]), angle)),), # Blade1 - (Path.CLOSEPOLY, mid_midcirc)]) - polys.append(PathPatch(mpath.Path(verts, codes), fc="k", ec="none",lw=200000000)) - polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - lines.append((node_geo, circ_edge)) + node_geo = list(node_coords.loc[i]) + if len(unique_angles) != 0 and "WT" in unique_angles[i]["sgen"]: + try: + angle = unique_angles[i]["sgen"]["WT"] + (angles[i] or 0) + except IndexError: + continue + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) + circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2 * size]), angle) + mid_midcirc = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + + codes, verts = zip(*[ + (Path.MOVETO, mid_midcirc), + (Path.LINETO, circ_topedge,), + (Path.LINETO, (circ_topedge + _rotate_dim2(np.array([- blade_coord1, - blade_coord1]), angle)),), + (Path.LINETO, (mid_midcirc + _rotate_dim2(np.array([- blade_coord2, + blade_coord2]), angle)),), + # Blade1 + (Path.CLOSEPOLY, mid_midcirc)]) + polys.append(PathPatch(mpath.Path(verts, codes), fc="k", ec="none", lw=200000000)) + polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + lines.append((node_geo, circ_edge)) - for j in range(3): - angle = j * 2 * math.pi / 3 - rotated_verts = [] - for vertex in verts: - # Calculate the vector from the center of the hub to the vertex - x_diff = vertex[0] - mid_midcirc[0] - y_diff = vertex[1] - mid_midcirc[1] + for j in range(3): + angle = j * 2 * math.pi / 3 + rotated_verts = [] + for vertex in verts: + # Calculate the vector from the center of the hub to the vertex + x_diff = vertex[0] - mid_midcirc[0] + y_diff = vertex[1] - mid_midcirc[1] - # Rotate the vector by the desired angle - rotated_x = x_diff * math.cos(angle) - y_diff * math.sin(angle) - rotated_y = x_diff * math.sin(angle) + y_diff * math.cos(angle) + # Rotate the vector by the desired angle + rotated_x = x_diff * math.cos(angle) - y_diff * math.sin(angle) + rotated_y = x_diff * math.sin(angle) + y_diff * math.cos(angle) - # Calculate the coordinates of the rotated vertex - rotated_vertex = [mid_midcirc[0] + rotated_x, mid_midcirc[1] + rotated_y] + # Calculate the coordinates of the rotated vertex + rotated_vertex = [mid_midcirc[0] + rotated_x, mid_midcirc[1] + rotated_y] - rotated_verts.append(rotated_vertex) + rotated_verts.append(rotated_vertex) - rotated_patch = PathPatch(mpath.Path(rotated_verts, codes), fc="k", ec="none") + rotated_patch = PathPatch(mpath.Path(rotated_verts, codes), fc="k", ec="none") - polys.append(rotated_patch) + polys.append(rotated_patch) - polys.append(Circle(mid_midcirc, hub_size, fc="k", ec=edgecolors[i])) # Center hub + polys.append(Circle(mid_midcirc, hub_size, fc="k", ec=edgecolors[i])) # Center hub - center_point = mid_midcirc # Define the center point of the wind turbine patch - rotation_angle = math.pi / 4 # Define the angle of rotation - if "PV" in unique_angles[i]["sgen"]: # PV patch - if len(unique_angles) != 0: - try: - angle = unique_angles[i]["sgen"]["PV"] + (angles[i] or 0) - except IndexError: - continue - else: - angle = angles[i] or 0 + if len(unique_angles) != 0 and "PV" in unique_angles[i]["sgen"]: - mid_rect = node_geo + _rotate_dim2(np.array([0, 2*size]), angle) - rect_lbottom = [mid_rect[0] - (pv_rect_size/4), mid_rect[1]] - pv_patch = Rectangle((rect_lbottom), pv_rect_size/2, pv_rect_size, angle=-angle * (180 / np.pi), + try: + angle = unique_angles[i]["sgen"]["PV"] + (angles[i] or 0) + except IndexError: + continue + mid_rect = node_geo + _rotate_dim2(np.array([0, 2 * size]), angle) + rect_lbottom = [mid_rect[0] - (pv_rect_size / 4), mid_rect[1]] + pv_patch = Rectangle((rect_lbottom), pv_rect_size / 2, pv_rect_size, angle=-angle * (180 / np.pi), rotation_point=(mid_rect[0], mid_rect[1]), ec="k", fc="none") polys.append(pv_patch) lines.append((node_geo, mid_rect)) triangle_base = pv_tri_size triangle_height = pv_tri_size * 0.75 triangle_points = [ - (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 2*size]), angle)), - (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 2*size]), angle)), - (mid_rect + _rotate_dim2(np.array([0, + 1.5*triangle_height]), angle)), + (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 2 * size]), angle)), + (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 2 * size]), angle)), + (mid_rect + _rotate_dim2(np.array([0, + 1.5 * triangle_height]), angle)), ] triangle_patch = Polygon(triangle_points, ec="k", fc="none") polys.append(triangle_patch) - if "wye" in unique_angles[i]["sgen"]: # Generic Patch - if len(unique_angles) != 0: - try: - angle = unique_angles[i]["sgen"]["wye"] + (angles[i] or 0) - except IndexError: - continue - else: - angle = angles[i] or 0 + if len(unique_angles) != 0 and "wye" in unique_angles[i]["sgen"]: + try: + angle = unique_angles[i]["sgen"]["wye"] + (angles[i] or 0) + except IndexError: + continue mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angle) @@ -418,6 +404,9 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): lines.append((perp_foot1, line_end1)) lines.append((perp_foot2, line_end2)) + else: + continue + return lines, polys, {"offset", "r_triangle", "patch_edgecolor", "patch_facecolor"} diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index 835e438fe..d854bc270 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -188,6 +188,20 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g gen_count = 0 load_count = 0 if plot_sgens and len(net.sgen): + sgen_types_counts = net.sgen[net.sgen.bus == i].type.value_counts() + PV = sgen_types_counts.get("PV", 0) + WT = sgen_types_counts.get("WT", 0) + WYE = sum(sgen_types_counts) - PV - WT + types = {} + if PV: + types["PV"] = PV + if WT: + types["WT"] = WT + if WYE: + types["wye"] = WYE + sgen_types[i] = types + if i not in patch_count_unique: + patch_count_unique[i] = {} try: sgen_count = len(sgen_types[i]) except KeyError: @@ -207,20 +221,7 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g except ZeroDivisionError: seperation_angle = None if plot_sgens and len(net.sgen): - sgen_types_counts = net.sgen[net.sgen.bus == i].type.value_counts() - PV = sgen_types_counts.get("PV", 0) - WT = sgen_types_counts.get("WT", 0) - WYE = sum(sgen_types_counts) - PV - WT - types = {} - if PV: - types["PV"] = PV - if WT: - types["WT"] = WT - if WYE: - types["wye"] = WYE - sgen_types[i] = types - if i not in patch_count_unique: - patch_count_unique[i] = {} + patch_count_unique[i]['sgen'] = dict( zip(sgen_types[i].keys(), [j * seperation_angle for j in range(sgen_count)])) @@ -238,7 +239,7 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g if 'load' not in patch_count_unique[i]: patch_count_unique[i]['load'] = [] patch_count_unique[i]['load'].extend( - [j * seperation_angle + sgen_count + gen_count * seperation_angle for j in range(load_count)]) + [j * seperation_angle + (sgen_count + gen_count) * seperation_angle for j in range(load_count)]) if plot_sgens and len(net.sgen): sgc = create_sgen_collection(net, size=sgen_size, unique_angles=patch_count_unique, orientation=orientation) From a295e259d3888c839d5c1802a3c5b1ef5b26fc5a Mon Sep 17 00:00:00 2001 From: hzraja Date: Wed, 16 Aug 2023 15:45:25 +0200 Subject: [PATCH 26/33] fixed pandapipes compatibility --- pandapower/plotting/collections.py | 30 ++++++++++++++--------------- pandapower/plotting/patch_makers.py | 25 ++++++++++++------------ pandapower/plotting/simple_plot.py | 19 ++++++++++++------ 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index 03c10895a..e6a076859 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -222,9 +222,9 @@ def _create_line2d_collection(coords, indices, infos=None, picker=False, **kwarg return lc -def _create_node_element_collection(node_coords, patch_maker, size=1., unique_angles=None, infos=None, +def _create_node_element_collection(node_coords, patch_maker, size=1., infos=None, repeat_infos=(1, 1), orientation=np.pi, picker=False, - patch_facecolor="w", patch_edgecolor="k", line_color="k", + patch_facecolor="w", patch_edgecolor="k", line_color="k",unique_angles=None, **kwargs): """ Creates matplotlib collections of node elements. All node element collections usually consist of @@ -961,7 +961,7 @@ def create_busbar_collection(net, buses=None, infofunc=None, cmap=None, norm=Non return lc -def create_load_collection(net, loads=None, size=1., unique_angles={}, infofunc=None, orientation=None, picker=False, +def create_load_collection(net, loads=None, size=1., infofunc=None, orientation=None, picker=False, unique_angles={}, **kwargs): """ Creates a matplotlib patch collection of pandapower loads. @@ -994,18 +994,17 @@ def create_load_collection(net, loads=None, size=1., unique_angles={}, infofunc= loads = get_index_array(loads, net.load.index) infos = [infofunc(i) for i in range(len(loads))] if infofunc is not None else [] - node_coords = net.bus_geodata.loc[:, ["x", "y"]] + node_coords = net.bus_geodata.loc[:, ["x", "y"]].values color = kwargs.pop("color", "k") load_pc, load_lc = _create_node_element_collection( - node_coords, load_patches, size=size, unique_angles=unique_angles, infos=infos, orientation=orientation, - picker=picker, line_color=color, **kwargs) + node_coords, load_patches, size=size, infos=infos, orientation=orientation, + picker=picker, line_color=color, unique_angles=unique_angles, **kwargs) return load_pc, load_lc -def create_gen_collection(net, gens=None, size=1., unique_angles=None, infofunc=None, orientation=None, picker=False, - **kwargs): +def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=None, picker=False,unique_angles=None, **kwargs): """ Creates a matplotlib patch collection of pandapower gens. @@ -1035,18 +1034,17 @@ def create_gen_collection(net, gens=None, size=1., unique_angles=None, infofunc= """ gens = get_index_array(gens, net.gen.index) infos = [infofunc(i) for i in range(len(gens))] if infofunc is not None else [] - node_coords = net.bus_geodata.loc[:, ["x", "y"]] + node_coords = net.bus_geodata.loc[:, ["x", "y"]].values color = kwargs.pop("color", "k") gen_pc, gen_lc = _create_node_element_collection( - node_coords, gen_patches, size=size, unique_angles=unique_angles, infos=infos, orientation=orientation, - picker=picker, line_color=color, **kwargs) + node_coords, gen_patches, size=size, infos=infos, orientation=orientation, + picker=picker, line_color=color, unique_angles=unique_angles, **kwargs) return gen_pc, gen_lc -def create_sgen_collection(net, sgens=None, size=1., unique_angles=None, infofunc=None, orientation=None, picker=False, - **kwargs): +def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation=None, picker=False, unique_angles=None, **kwargs): """ Creates a matplotlib patch collection of pandapower sgen. @@ -1076,13 +1074,13 @@ def create_sgen_collection(net, sgens=None, size=1., unique_angles=None, infofun """ infos = [infofunc(i) for i in range(len(sgens))] if infofunc is not None else [] - node_coords = net.bus_geodata.loc[:, ["x", "y"]] + node_coords = net.bus_geodata.loc[:, ["x", "y"]].values color = kwargs.pop("color", "k") sgen_pc, sgen_lc = _create_node_element_collection( - node_coords, sgen_patches, size=size, unique_angles=unique_angles, infos=infos, orientation=orientation, - picker=picker, line_color=color, **kwargs) + node_coords, sgen_patches, size=size, infos=infos, orientation=orientation, + picker=picker, line_color=color,unique_angles=unique_angles, **kwargs) return sgen_pc, sgen_lc diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index cebfb3549..833186923 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -194,8 +194,11 @@ def load_patches(node_coords, size, angles, unique_angles, **kwargs): facecolors = get_color_list(facecolor, len(node_coords)) polys, lines = list(), list() - for i in node_coords.index: - node_geo = list(node_coords.loc[i]) + if unique_angles is None: + unique_angles = {} + + for i, node_geo in enumerate(node_coords): + if len(unique_angles) != 0: if "load" in unique_angles[i] and unique_angles[i]["load"] != []: try: @@ -244,8 +247,10 @@ def gen_patches(node_coords, size, angles, unique_angles, **kwargs): edgecolors = get_color_list(edgecolor, len(node_coords)) facecolors = get_color_list(facecolor, len(node_coords)) - for i in node_coords.index: - node_geo = list(node_coords.loc[i]) + if unique_angles is None: + unique_angles = {} + + for i, node_geo in enumerate(node_coords): if len(unique_angles) != 0: if "gen" in unique_angles[i] and unique_angles[i]["gen"] != []: try: @@ -256,7 +261,6 @@ def gen_patches(node_coords, size, angles, unique_angles, **kwargs): continue else: angle = all_angles[i] or 0 - p2 = node_geo + _rotate_dim2(np.array([0, size + offset]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) polys.append(Circle(p2, size, fc=facecolors[i], ec=edgecolors[i])) @@ -307,9 +311,10 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): facecolors = get_color_list(facecolor, len(node_coords)) Path = mpath.Path - for i in node_coords.index: - node_geo = list(node_coords.loc[i]) + if unique_angles is None: + unique_angles = {} + for i, node_geo in enumerate(node_coords): if len(unique_angles) != 0 and "WT" in unique_angles[i]["sgen"]: try: angle = unique_angles[i]["sgen"]["WT"] + (angles[i] or 0) @@ -354,10 +359,7 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): polys.append(Circle(mid_midcirc, hub_size, fc="k", ec=edgecolors[i])) # Center hub - - if len(unique_angles) != 0 and "PV" in unique_angles[i]["sgen"]: - try: angle = unique_angles[i]["sgen"]["PV"] + (angles[i] or 0) except IndexError: @@ -378,9 +380,7 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): triangle_patch = Polygon(triangle_points, ec="k", fc="none") polys.append(triangle_patch) - if len(unique_angles) != 0 and "wye" in unique_angles[i]["sgen"]: - try: angle = unique_angles[i]["sgen"]["wye"] + (angles[i] or 0) except IndexError: @@ -403,7 +403,6 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): lines.append((node_geo, circ_edge)) lines.append((perp_foot1, line_end1)) lines.append((perp_foot2, line_end2)) - else: continue diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index d854bc270..4d6c2eb31 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -193,24 +193,30 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g WT = sgen_types_counts.get("WT", 0) WYE = sum(sgen_types_counts) - PV - WT types = {} + if PV: types["PV"] = PV + if WT: types["WT"] = WT + if WYE: types["wye"] = WYE sgen_types[i] = types + if i not in patch_count_unique: patch_count_unique[i] = {} try: sgen_count = len(sgen_types[i]) except KeyError: sgen_count = 0 + if plot_gens and len(net.gen): try: gen_count = len(pp.get_connected_elements_dict(net, element_types=["gen"], buses=i)) except KeyError: gen_count = 0 + if plot_loads and len(net.load): try: load_count = len(pp.get_connected_elements_dict(net, element_types=["load"], buses=i)) @@ -221,13 +227,13 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g except ZeroDivisionError: seperation_angle = None if plot_sgens and len(net.sgen): - patch_count_unique[i]['sgen'] = dict( zip(sgen_types[i].keys(), [j * seperation_angle for j in range(sgen_count)])) if plot_gens and len(net.gen): if i not in patch_count_unique: patch_count_unique[i] = {} + if 'gen' not in patch_count_unique[i]: patch_count_unique[i]['gen'] = [] patch_count_unique[i]['gen'].extend( @@ -236,21 +242,22 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g if plot_loads and len(net.load): if i not in patch_count_unique: patch_count_unique[i] = {} + if 'load' not in patch_count_unique[i]: patch_count_unique[i]['load'] = [] patch_count_unique[i]['load'].extend( [j * seperation_angle + (sgen_count + gen_count) * seperation_angle for j in range(load_count)]) if plot_sgens and len(net.sgen): - sgc = create_sgen_collection(net, size=sgen_size, unique_angles=patch_count_unique, orientation=orientation) + sgc = create_sgen_collection(net, size=sgen_size, orientation=orientation,unique_angles=patch_count_unique) collections.append(sgc) - if plot_gens and len(net.gen): - gc = create_gen_collection(net, size=gen_size, unique_angles=patch_count_unique, orientation=orientation) + if plot_gens and len(net.gen): + gc = create_gen_collection(net, size=gen_size, orientation=orientation,unique_angles=patch_count_unique) collections.append(gc) - if plot_loads and len(net.load): - lc = create_load_collection(net, size=load_size, unique_angles=patch_count_unique, orientation=orientation) + if plot_loads and len(net.load): + lc = create_load_collection(net, size=load_size, orientation=orientation, unique_angles=patch_count_unique) collections.append(lc) if len(net.switch): From 488db49430edb0212b762c3184bc277fe5b2e157 Mon Sep 17 00:00:00 2001 From: hzraja Date: Wed, 16 Aug 2023 20:10:58 +0200 Subject: [PATCH 27/33] fixed codacy errors --- pandapower/plotting/collections.py | 39 +----------------------------- pandapower/plotting/simple_plot.py | 3 --- 2 files changed, 1 insertion(+), 41 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index cc6e27831..1163c858e 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -961,7 +961,7 @@ def create_busbar_collection(net, buses=None, infofunc=None, cmap=None, norm=Non return lc -def create_load_collection(net, loads=None, size=1., infofunc=None, orientation=None, picker=False, unique_angles={}, +def create_load_collection(net, loads=None, size=1., infofunc=None, orientation=None, picker=False, unique_angles=None, **kwargs): """ Creates a matplotlib patch collection of pandapower loads. @@ -990,8 +990,6 @@ def create_load_collection(net, loads=None, size=1., infofunc=None, orientation= **load_lc** - line collection """ - # sgens = get_index_array(sgens, net.sgen.index) - loads = get_index_array(loads, net.load.index) infos = [infofunc(i) for i in range(len(loads))] if infofunc is not None else [] node_coords = net.bus_geodata.loc[:, ["x", "y"]].values @@ -1035,9 +1033,7 @@ def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=N gens = get_index_array(gens, net.gen.index) infos = [infofunc(i) for i in range(len(gens))] if infofunc is not None else [] node_coords = net.bus_geodata.loc[:, ["x", "y"]].values - color = kwargs.pop("color", "k") - gen_pc, gen_lc = _create_node_element_collection( node_coords, gen_patches, size=size, infos=infos, orientation=orientation, picker=picker, line_color=color, unique_angles=unique_angles, **kwargs) @@ -1072,11 +1068,8 @@ def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation **sgen_lc** - line collection """ - infos = [infofunc(i) for i in range(len(sgens))] if infofunc is not None else [] node_coords = net.bus_geodata.loc[:, ["x", "y"]].values - - color = kwargs.pop("color", "k") sgen_pc, sgen_lc = _create_node_element_collection( node_coords, sgen_patches, size=size, infos=infos, orientation=orientation, @@ -1415,34 +1408,4 @@ def add_collections_to_axes(ax, collections, plot_colorbars=True, copy_collectio if __name__ == "__main__": - # if 0: - # import pandapower as pp - # - # ntw = pp.create_empty_network() - # b1 = pp.create_bus(ntw, 10, geodata=(5, 10)) - # b2 = pp.create_bus(ntw, 0.4, geodata=(5, 15)) - # b3 = pp.create_bus(ntw, 0.4, geodata=(0, 22)) - # b4 = pp.create_bus(ntw, 0.4, geodata=(8, 20)) - # pp.create_gen(ntw, b1, p_mw=0.1) - # pp.create_load(ntw, b3, p_mw=0.1) - # pp.create_ext_grid(ntw, b4) - # - # pp.create_line(ntw, b2, b3, 2.0, std_type="NAYY 4x50 SE") - # pp.create_line(ntw, b2, b4, 2.0, std_type="NAYY 4x50 SE") - # pp.create_transformer(ntw, b1, b2, std_type="0.63 MVA 10/0.4 kV") - # pp.create_transformer(ntw, b3, b4, std_type="0.63 MVA 10/0.4 kV") - # - # bus_col = create_bus_collection(ntw, size=0.2, color="k") - # line_col = create_line_collection(ntw, use_line_geodata=False, color="k", linewidth=3.) - # lt, bt = create_trafo_collection(ntw, size=2, linewidth=3.) - # load_col1, load_col2 = create_load_collection(ntw, linewidth=2., - # infofunc=lambda x: ("load", x)) - # gen1, gen2 = create_gen_collection(ntw, linewidth=2., - # infofunc=lambda x: ("gen", x)) - # eg1, eg2 = create_ext_grid_collection(ntw, size=2., - # infofunc=lambda x: ("ext_grid", x)) - # - # draw_collections([bus_col, line_col, load_col1, load_col2, gen1, gen2, lt, bt, eg1, eg2]) - # else: - # pass pass \ No newline at end of file diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index dc887e502..70d1352cf 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -177,9 +177,6 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g use_line_geodata=not use_bus_geodata, zorder=12, color=switch_color) collections.append(sc) - total_patches = len(get_connected_elements_dict(net, element_types=["sgen", "gen", "load"], buses=1)) + len( - net.sgen.type.unique()) - patch_count_unique = {} sgen_types = {} From 00179175335fad28d936aa059502ae103d9e73bd Mon Sep 17 00:00:00 2001 From: hzraja Date: Thu, 16 Nov 2023 13:47:13 +0100 Subject: [PATCH 28/33] collections_implementation --- main.py | 37 ++++ pandapower/plotting/collections.py | 23 ++- pandapower/plotting/patch_makers.py | 46 +++-- pandapower/plotting/simple_plot.py | 234 ++++++++++++++++++-------- tutorials/building_a_controller.ipynb | 2 +- 5 files changed, 247 insertions(+), 95 deletions(-) create mode 100644 main.py diff --git a/main.py b/main.py new file mode 100644 index 000000000..b69ac6407 --- /dev/null +++ b/main.py @@ -0,0 +1,37 @@ +import matplotlib +import matplotlib.pyplot as plt + +from copy import deepcopy +import pandapower as pp +import pandapower.plotting as plot +from pandapower import networks as nw +from pandapower.networks import example_simple +from IPython.display import display, Markdown + +net = nw.mv_oberrhein() +pp.create_sgens(net, buses=net.bus.index[0:50], p_mw=1, type=["wye"]*50) + +net.sgen.type.loc[0:50] = "WT" +bc = plot.create_bus_collection(net, net.bus.index, size=80, color="red", zorder=1) +# sc= plot.create_sgen_collection(net, sgens=net.sgen.index[0:50], size=80,orientation=0, picker=False) +#sc= plot.create_sgen_collection(net, sgens=net.sgen.index, size=80,orientation=1.4, picker=False, patch_type=["wye", "WT", "PV"]) + +# wind_turbine_sgen = net.sgen.loc[net.sgen.type == "WT"].index +# wt_c = plot.create_sgen_collection(net, sgens=wind_turbine_sgen, size=80, orientation=1.4, picker=False, patch_type="WT") + + +# pc_sgen = net.sgen.loc[net.sgen.type == "PV"].index +# pv_c = plot.create_sgen_collection(net, sgens=pc_sgen, size=80, orientation=1.4, picker=False, patch_type="PV") + + +#todo for simple plot +# orientation_list = [0, 180] +# for type in net.sgen.type.unique(): +# sgen_indices = net.sgen.loc[net.sgen.type == type].index +# s_c = plot.create_sgen_collection(net, sgens=sgen_indices, size=80, orientation="insert angles from your method", picker=False, patch_type=type) +# collections.append(s_c) + +plot.draw_collections([bc], figsize=(8,6)) + +# pp.plotting.simple_plot(net, plot_loads=True, plot_gens=False, plot_sgens=True,orientation=0, load_size=2.5, gen_size=2.0,sgen_size=2,additional_patches=False); + diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index 648eb3c6c..b403bc674 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -9,7 +9,6 @@ import numpy as np from pandas import isnull - try: import matplotlib.pyplot as plt from matplotlib.collections import LineCollection, PatchCollection, Collection @@ -224,7 +223,7 @@ def _create_line2d_collection(coords, indices, infos=None, picker=False, **kwarg def _create_node_element_collection(node_coords, patch_maker, size=1., infos=None, repeat_infos=(1, 1), orientation=np.pi, picker=False, - patch_facecolor="w", patch_edgecolor="k", line_color="k",unique_angles=None, + patch_facecolor="w", patch_edgecolor="k", line_color="k",patch_type=None,unique_angles=None, **kwargs): """ Creates matplotlib collections of node elements. All node element collections usually consist of @@ -280,7 +279,7 @@ def _create_node_element_collection(node_coords, patch_maker, size=1., infos=Non linewidths = kwargs.pop("linewidth", linewidths) linewidths = kwargs.pop("lw", linewidths) lines, polys, popped_keywords = patch_maker( - node_coords, size, angles, unique_angles=unique_angles, patch_facecolor=patch_facecolor, patch_edgecolor=patch_edgecolor, + node_coords, size, angles,patch_type = patch_type, unique_angles=unique_angles, patch_facecolor=patch_facecolor, patch_edgecolor=patch_edgecolor, **kwargs) for kw in set(popped_keywords) & set(kwargs.keys()): kwargs.pop(kw) @@ -996,6 +995,10 @@ def create_load_collection(net, loads=None, size=1., infofunc=None, orientation= **load_lc** - line collection """ + from pandapower.plotting.simple_plot import calculate_unique_angles + + if unique_angles == None: + unique_angles = calculate_unique_angles(net) loads = get_index_array(loads, net.load.index) infos = [infofunc(i) for i in range(len(loads))] if infofunc is not None else [] node_coords = net.bus_geodata.loc[:, ["x", "y"]].values @@ -1036,6 +1039,10 @@ def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=N **gen_lc** - line collection """ + from pandapower.plotting.simple_plot import calculate_unique_angles + + if unique_angles == None: + unique_angles = calculate_unique_angles(net) gens = get_index_array(gens, net.gen.index) infos = [infofunc(i) for i in range(len(gens))] if infofunc is not None else [] node_coords = net.bus_geodata.loc[:, ["x", "y"]].values @@ -1046,7 +1053,7 @@ def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=N return gen_pc, gen_lc -def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation=None, picker=False, unique_angles=None, **kwargs): +def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation=None, picker=False, patch_type=None, unique_angles=None, **kwargs): """ Creates a matplotlib patch collection of pandapower sgen. @@ -1074,12 +1081,18 @@ def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation **sgen_lc** - line collection """ + from pandapower.plotting.simple_plot import calculate_unique_angles + + if unique_angles == None: + unique_angles = calculate_unique_angles(net) + + infos = [infofunc(i) for i in range(len(sgens))] if infofunc is not None else [] node_coords = net.bus_geodata.loc[:, ["x", "y"]].values color = kwargs.pop("color", "k") sgen_pc, sgen_lc = _create_node_element_collection( node_coords, sgen_patches, size=size, infos=infos, orientation=orientation, - picker=picker, line_color=color,unique_angles=unique_angles, **kwargs) + picker=picker, line_color=color,patch_type=patch_type,unique_angles=unique_angles, **kwargs) return sgen_pc, sgen_lc diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 833186923..af2d97832 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -275,7 +275,7 @@ def gen_patches(node_coords, size, angles, unique_angles, **kwargs): return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} -def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): +def sgen_patches(node_coords, size, angles,patch_type, unique_angles, **kwargs): """ Creation function of patches for static generators. @@ -315,11 +315,10 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): unique_angles = {} for i, node_geo in enumerate(node_coords): - if len(unique_angles) != 0 and "WT" in unique_angles[i]["sgen"]: - try: - angle = unique_angles[i]["sgen"]["WT"] + (angles[i] or 0) - except IndexError: - continue + + if len(unique_angles) != 0 and "WT" in unique_angles[i]["sgen"] or patch_type=="WT": + angle = (unique_angles[i]["sgen"]["WT"] + (angles[i] or 0)) or angles[i] + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2 * size]), angle) @@ -359,11 +358,9 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): polys.append(Circle(mid_midcirc, hub_size, fc="k", ec=edgecolors[i])) # Center hub - if len(unique_angles) != 0 and "PV" in unique_angles[i]["sgen"]: - try: - angle = unique_angles[i]["sgen"]["PV"] + (angles[i] or 0) - except IndexError: - continue + if len(unique_angles) != 0 and "PV" in unique_angles[i]["sgen"] or patch_type=="PV": + angle = unique_angles[i]["sgen"]["PV"] + (angles[i] or 0) or angles[i] + mid_rect = node_geo + _rotate_dim2(np.array([0, 2 * size]), angle) rect_lbottom = [mid_rect[0] - (pv_rect_size / 4), mid_rect[1]] pv_patch = Rectangle((rect_lbottom), pv_rect_size / 2, pv_rect_size, angle=-angle * (180 / np.pi), @@ -380,11 +377,9 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): triangle_patch = Polygon(triangle_points, ec="k", fc="none") polys.append(triangle_patch) - if len(unique_angles) != 0 and "wye" in unique_angles[i]["sgen"]: - try: - angle = unique_angles[i]["sgen"]["wye"] + (angles[i] or 0) - except IndexError: - continue + if len(unique_angles) != 0 and "wye" in unique_angles[i]["sgen"] or patch_type=="wye": + angle = unique_angles[i]["sgen"]["wye"] + (angles[i] or 0) or angles[i] + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angle) @@ -403,6 +398,25 @@ def sgen_patches(node_coords, size, angles, unique_angles, **kwargs): lines.append((node_geo, circ_edge)) lines.append((perp_foot1, line_end1)) lines.append((perp_foot2, line_end2)) + if len(unique_angles) == 0 : + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) + mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angles[i]) + mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angles[i]) + # dropped perpendicular foot of triangle1 + perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) + line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2.5 * r_triangle, 0]), angles[i]) + perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) + line_end2 = perp_foot2 + + _rotate_dim2(np.array([2.5 * r_triangle, 0]), angles[i]) + polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, + orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) + polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, + orientation=np.pi - angles[i], fc=facecolors[i], + ec=edgecolors[i])) + lines.append((node_geo, circ_edge)) + lines.append((perp_foot1, line_end1)) + lines.append((perp_foot2, line_end2)) else: continue diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index 70d1352cf..36c45bda7 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -30,7 +30,7 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_grid_size=1.0, trafo_size=1.0, plot_loads=False, plot_gens=False, plot_sgens=False, orientation=None, load_size=1.0, gen_size=1.0, sgen_size=1.0, - switch_size=2.0, switch_distance=1.0, plot_line_switches=False, scale_size=True, + switch_size=2.0, switch_distance=1.0, plot_line_switches=False, scale_size=True, additional_patches=None, bus_color='b', line_color='grey', dcline_color='c', trafo_color='k', ext_grid_color='y', switch_color='k', library='igraph', show_plot=True, ax=None): """ @@ -176,102 +176,190 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g net, size=switch_size, distance_to_bus=switch_distance, use_line_geodata=not use_bus_geodata, zorder=12, color=switch_color) collections.append(sc) + if additional_patches: + patch_count_unique = {} + sgen_types = {} + + for index, bus in enumerate(net.bus_geodata.index): + sgen_count = 0 + gen_count = 0 + load_count = 0 + if plot_sgens and len(net.sgen): + sgen_types_counts = net.sgen[net.sgen.bus == index].type.value_counts() + PV = sgen_types_counts.get("PV", 0) + WT = sgen_types_counts.get("WT", 0) + WYE = sum(sgen_types_counts) - PV - WT + types = {} + if PV: + types["PV"] = PV + + if WT: + types["WT"] = WT + + if WYE: + types["wye"] = WYE + sgen_types[index] = types + + if index not in patch_count_unique: + patch_count_unique[index] = {} + try: + sgen_count = len(sgen_types[index]) + except KeyError: + sgen_count = 0 + + if plot_gens and len(net.gen): + try: + gen_count = len(pp.get_connected_elements_dict(net, element_types=["gen"], buses=index)) + except KeyError: + gen_count = 0 + + if plot_loads and len(net.load): + try: + load_count = len(pp.get_connected_elements_dict(net, element_types=["load"], buses=index)) + except KeyError: + load_count = 0 + total_count = sgen_count + gen_count + load_count + try: seperation_angle = 2 * math.pi / total_count + except ZeroDivisionError: seperation_angle = None + + if plot_sgens and len(net.sgen): + patch_count_unique[index]['sgen'] = dict( + zip(sgen_types[index].keys(), [j * seperation_angle for j in range(sgen_count)])) + + if plot_gens and len(net.gen): + if index not in patch_count_unique: + patch_count_unique[index] = {} + + if 'gen' not in patch_count_unique[index]: + patch_count_unique[index]['gen'] = [] + patch_count_unique[index]['gen'].extend( + [j * seperation_angle + sgen_count * seperation_angle for j in range(gen_count)]) + + if plot_loads and len(net.load): + if index not in patch_count_unique: + patch_count_unique[index] = {} + + if 'load' not in patch_count_unique[index]: + patch_count_unique[index]['load'] = [] + patch_count_unique[index]['load'].extend( + [j * seperation_angle + (sgen_count + gen_count) * seperation_angle for j in range(load_count)]) + if plot_sgens and len(net.sgen): + sgc = create_sgen_collection(net, size=sgen_size, orientation=orientation, unique_angles=patch_count_unique) + collections.append(sgc) - patch_count_unique = {} - sgen_types = {} + if plot_gens and len(net.gen): + gc = create_gen_collection(net, size=gen_size, orientation=orientation, unique_angles=patch_count_unique) + collections.append(gc) - for i in net.bus_geodata.index: - sgen_count = 0 - gen_count = 0 - load_count = 0 - if plot_sgens and len(net.sgen): - sgen_types_counts = net.sgen[net.sgen.bus == i].type.value_counts() - PV = sgen_types_counts.get("PV", 0) - WT = sgen_types_counts.get("WT", 0) - WYE = sum(sgen_types_counts) - PV - WT - types = {} + if plot_loads and len(net.load): + lc = create_load_collection(net, size=load_size, orientation=orientation, unique_angles=patch_count_unique) + collections.append(lc) - if PV: - types["PV"] = PV + if len(net.switch): + bsc = create_bus_bus_switch_collection(net, size=switch_size) + collections.append(bsc) - if WT: - types["WT"] = WT + ax = draw_collections(collections, ax=ax) + if show_plot: + if not MATPLOTLIB_INSTALLED: + soft_dependency_error(str(sys._getframe().f_code.co_name) + "()", "matplotlib") + plt.show() + return ax - if WYE: - types["wye"] = WYE - sgen_types[i] = types + else: - if i not in patch_count_unique: - patch_count_unique[i] = {} - try: - sgen_count = len(sgen_types[i]) - except KeyError: - sgen_count = 0 + if plot_sgens and len(net.sgen): + sgc = create_sgen_collection(net, size=sgen_size, orientation=orientation) + collections.append(sgc) if plot_gens and len(net.gen): - try: - gen_count = len(pp.get_connected_elements_dict(net, element_types=["gen"], buses=i)) - except KeyError: - gen_count = 0 + gc = create_gen_collection(net, size=gen_size, orientation=orientation) + collections.append(gc) if plot_loads and len(net.load): - try: - load_count = len(pp.get_connected_elements_dict(net, element_types=["load"], buses=i)) - except KeyError: - load_count = 0 - total_count = sgen_count + gen_count + load_count - try: seperation_angle = 2 * math.pi / total_count - except ZeroDivisionError: seperation_angle = None + lc = create_load_collection(net, size=load_size, orientation=orientation) + collections.append(lc) - if plot_sgens and len(net.sgen): - patch_count_unique[i]['sgen'] = dict( - zip(sgen_types[i].keys(), [j * seperation_angle for j in range(sgen_count)])) + if len(net.switch): + bsc = create_bus_bus_switch_collection(net, size=switch_size) + collections.append(bsc) - if plot_gens and len(net.gen): - if i not in patch_count_unique: - patch_count_unique[i] = {} + ax = draw_collections(collections, ax=ax) + if show_plot: + if not MATPLOTLIB_INSTALLED: + soft_dependency_error(str(sys._getframe().f_code.co_name) + "()", "matplotlib") + plt.show() + return ax - if 'gen' not in patch_count_unique[i]: - patch_count_unique[i]['gen'] = [] - patch_count_unique[i]['gen'].extend( - [j * seperation_angle + sgen_count * seperation_angle for j in range(gen_count)]) +def calculate_unique_angles(net): + patch_count_unique = {} + sgen_types = {} - if plot_loads and len(net.load): - if i not in patch_count_unique: - patch_count_unique[i] = {} + for index, bus in enumerate(net.bus_geodata.index): + sgen_count = 0 + gen_count = 0 + load_count = 0 - if 'load' not in patch_count_unique[i]: - patch_count_unique[i]['load'] = [] - patch_count_unique[i]['load'].extend( - [j * seperation_angle + (sgen_count + gen_count) * seperation_angle for j in range(load_count)]) + sgen_types_counts = net.sgen[net.sgen.bus == index].type.value_counts() + PV = sgen_types_counts.get("PV", 0) + WT = sgen_types_counts.get("WT", 0) + WYE = sum(sgen_types_counts) - PV - WT + types = {} + if PV: + types["PV"] = PV + + if WT: + types["WT"] = WT + + if WYE: + types["wye"] = WYE + sgen_types[index] = types + + if index not in patch_count_unique: + patch_count_unique[index] = {} + try: + sgen_count = len(sgen_types[index]) + except KeyError: + sgen_count = 0 + + try: + gen_count = len(pp.get_connected_elements_dict(net, element_types=["gen"], buses=index)) + except KeyError: + gen_count = 0 + + try: + load_count = len(pp.get_connected_elements_dict(net, element_types=["load"], buses=index)) + except KeyError: + load_count = 0 - if plot_sgens and len(net.sgen): - sgc = create_sgen_collection(net, size=sgen_size, orientation=orientation,unique_angles=patch_count_unique) - collections.append(sgc) + total_count = sgen_count + gen_count + load_count + try: + seperation_angle = 2 * math.pi / total_count + except ZeroDivisionError: + seperation_angle = None - if plot_gens and len(net.gen): - gc = create_gen_collection(net, size=gen_size, orientation=orientation,unique_angles=patch_count_unique) - collections.append(gc) + patch_count_unique[index]['sgen'] = dict( + zip(sgen_types[index].keys(), [j * seperation_angle for j in range(sgen_count)])) - if plot_loads and len(net.load): - lc = create_load_collection(net, size=load_size, orientation=orientation, unique_angles=patch_count_unique) - collections.append(lc) + if index not in patch_count_unique: + patch_count_unique[index] = {} - if len(net.switch): - bsc = create_bus_bus_switch_collection(net, size=switch_size) - collections.append(bsc) + if 'gen' not in patch_count_unique[index]: + patch_count_unique[index]['gen'] = [] + patch_count_unique[index]['gen'].extend( + [j * seperation_angle + sgen_count * seperation_angle for j in range(gen_count)]) - ax = draw_collections(collections, ax=ax) - if show_plot: - if not MATPLOTLIB_INSTALLED: - soft_dependency_error(str(sys._getframe().f_code.co_name) + "()", "matplotlib") - plt.show() - return ax + if index not in patch_count_unique: + patch_count_unique[index] = {} + if 'load' not in patch_count_unique[index]: + patch_count_unique[index]['load'] = [] + patch_count_unique[index]['load'].extend( + [j * seperation_angle + (sgen_count + gen_count) * seperation_angle for j in range(load_count)]) + return patch_count_unique if __name__ == "__main__": import pandapower.networks as nw - net = nw.case145() # net = nw.create_cigre_network_mv() # net = nw.mv_oberrhein() diff --git a/tutorials/building_a_controller.ipynb b/tutorials/building_a_controller.ipynb index c062389d4..0cf1dde15 100644 --- a/tutorials/building_a_controller.ipynb +++ b/tutorials/building_a_controller.ipynb @@ -276,7 +276,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.8.16" } }, "nbformat": 4, From a6a4d3edc9ec0980619b12d522123776864b378b Mon Sep 17 00:00:00 2001 From: hzraja Date: Fri, 8 Dec 2023 00:36:53 +0100 Subject: [PATCH 29/33] seperated unique_angles and draw by type in draw collections --- pandapower/plotting/collections.py | 8 +- pandapower/plotting/patch_makers.py | 203 ++++++++++++++-------------- 2 files changed, 103 insertions(+), 108 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index b403bc674..f786b8bce 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -223,7 +223,7 @@ def _create_line2d_collection(coords, indices, infos=None, picker=False, **kwarg def _create_node_element_collection(node_coords, patch_maker, size=1., infos=None, repeat_infos=(1, 1), orientation=np.pi, picker=False, - patch_facecolor="w", patch_edgecolor="k", line_color="k",patch_type=None,unique_angles=None, + patch_facecolor="w", patch_edgecolor="k", line_color="k",patch_type=None,unique_angles=None,draw_sgens_by_type=None, **kwargs): """ Creates matplotlib collections of node elements. All node element collections usually consist of @@ -279,7 +279,7 @@ def _create_node_element_collection(node_coords, patch_maker, size=1., infos=Non linewidths = kwargs.pop("linewidth", linewidths) linewidths = kwargs.pop("lw", linewidths) lines, polys, popped_keywords = patch_maker( - node_coords, size, angles,patch_type = patch_type, unique_angles=unique_angles, patch_facecolor=patch_facecolor, patch_edgecolor=patch_edgecolor, + node_coords, size, angles,patch_type = patch_type, unique_angles=unique_angles,draw_sgens_by_type=draw_sgens_by_type, patch_facecolor=patch_facecolor, patch_edgecolor=patch_edgecolor, **kwargs) for kw in set(popped_keywords) & set(kwargs.keys()): kwargs.pop(kw) @@ -1053,7 +1053,7 @@ def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=N return gen_pc, gen_lc -def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation=None, picker=False, patch_type=None, unique_angles=None, **kwargs): +def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation=None, picker=False, patch_type=None, unique_angles=None,draw_sgens_by_type=None, **kwargs): """ Creates a matplotlib patch collection of pandapower sgen. @@ -1092,7 +1092,7 @@ def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation color = kwargs.pop("color", "k") sgen_pc, sgen_lc = _create_node_element_collection( node_coords, sgen_patches, size=size, infos=infos, orientation=orientation, - picker=picker, line_color=color,patch_type=patch_type,unique_angles=unique_angles, **kwargs) + picker=picker, line_color=color,patch_type=patch_type,unique_angles=unique_angles,draw_sgens_by_type=draw_sgens_by_type, **kwargs) return sgen_pc, sgen_lc diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index af2d97832..48e15a756 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -24,6 +24,85 @@ logger = logging.getLogger(__name__) +def wye_patch(node_geo, offset, size, r_triangle, angle,polys,lines, facecolors, edgecolors,i): + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) + mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angle) + mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angle) + # dropped perpendicular foot of triangle1 + perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angle) + line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2.5 * r_triangle, 0]), angle) + perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angle) + line_end2 = perp_foot2 + + _rotate_dim2(np.array([2.5 * r_triangle, 0]), angle) + polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, + orientation=-angle, fc=facecolors[i], ec=edgecolors[i])) + polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, + orientation=np.pi - angle, fc=facecolors[i], + ec=edgecolors[i])) + lines.append((node_geo, circ_edge)) + lines.append((perp_foot1, line_end1)) + lines.append((perp_foot2, line_end2)) + + +def wt_patch(node_geo, offset, size, angle, polys, lines, facecolors, edgecolors, blade_coord1, blade_coord2,hub_size, Path, i): + mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) + circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2 * size]), angle) + mid_midcirc = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) + + codes, verts = zip(*[ + (Path.MOVETO, mid_midcirc), + (Path.LINETO, circ_topedge,), + (Path.LINETO, (circ_topedge + _rotate_dim2(np.array([- blade_coord1, - blade_coord1]), angle)),), + (Path.LINETO, (mid_midcirc + _rotate_dim2(np.array([- blade_coord2, + blade_coord2]), angle)),), + # Blade1 + (Path.CLOSEPOLY, mid_midcirc)]) + polys.append(PathPatch(mpath.Path(verts, codes), fc="k", ec="none", lw=200000000)) + polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) + lines.append((node_geo, circ_edge)) + + for j in range(3): + angle = j * 2 * math.pi / 3 + rotated_verts = [] + for vertex in verts: + # Calculate the vector from the center of the hub to the vertex + x_diff = vertex[0] - mid_midcirc[0] + y_diff = vertex[1] - mid_midcirc[1] + + # Rotate the vector by the desired angle + rotated_x = x_diff * math.cos(angle) - y_diff * math.sin(angle) + rotated_y = x_diff * math.sin(angle) + y_diff * math.cos(angle) + + # Calculate the coordinates of the rotated vertex + rotated_vertex = [mid_midcirc[0] + rotated_x, mid_midcirc[1] + rotated_y] + + rotated_verts.append(rotated_vertex) + + rotated_patch = PathPatch(mpath.Path(rotated_verts, codes), fc="k", ec="none") + + polys.append(rotated_patch) + + polys.append(Circle(mid_midcirc, hub_size, fc="k", ec=edgecolors[i])) # Center hub + +def pv_patch(node_geo, offset, size, angle, pv_rect_size,pv_tri_size, polys,lines, facecolors, edgecolors,i): + mid_rect = node_geo + _rotate_dim2(np.array([0, 2 * size]), angle) + rect_lbottom = [mid_rect[0] - (pv_rect_size / 4), mid_rect[1]] + pv_patch = Rectangle((rect_lbottom), pv_rect_size / 2, pv_rect_size, angle=-angle * (180 / np.pi), + rotation_point=(mid_rect[0], mid_rect[1]), ec="k", fc="none") + polys.append(pv_patch) + lines.append((node_geo, mid_rect)) + triangle_base = pv_tri_size + triangle_height = pv_tri_size * 0.75 + triangle_points = [ + (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 2 * size]), angle)), + (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 2 * size]), angle)), + (mid_rect + _rotate_dim2(np.array([0, + 1.5 * triangle_height]), angle)), + ] + triangle_patch = Polygon(triangle_points, ec="k", fc="none") + polys.append(triangle_patch) + + def node_patches(node_coords, size, patch_type, colors=None, **kwargs): """ Creates node patches from coordinates translating the patch type into patches. @@ -275,7 +354,7 @@ def gen_patches(node_coords, size, angles, unique_angles, **kwargs): return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} -def sgen_patches(node_coords, size, angles,patch_type, unique_angles, **kwargs): +def sgen_patches(node_coords, size, angles,patch_type, unique_angles,draw_sgens_by_type=None, **kwargs): """ Creation function of patches for static generators. @@ -315,110 +394,26 @@ def sgen_patches(node_coords, size, angles,patch_type, unique_angles, **kwargs): unique_angles = {} for i, node_geo in enumerate(node_coords): - - if len(unique_angles) != 0 and "WT" in unique_angles[i]["sgen"] or patch_type=="WT": - angle = (unique_angles[i]["sgen"]["WT"] + (angles[i] or 0)) or angles[i] - - mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) - circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) - circ_topedge = circ_edge + _rotate_dim2(np.array([0, 2 * size]), angle) - mid_midcirc = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) - - codes, verts = zip(*[ - (Path.MOVETO, mid_midcirc), - (Path.LINETO, circ_topedge,), - (Path.LINETO, (circ_topedge + _rotate_dim2(np.array([- blade_coord1, - blade_coord1]), angle)),), - (Path.LINETO, (mid_midcirc + _rotate_dim2(np.array([- blade_coord2, + blade_coord2]), angle)),), - # Blade1 - (Path.CLOSEPOLY, mid_midcirc)]) - polys.append(PathPatch(mpath.Path(verts, codes), fc="k", ec="none", lw=200000000)) - polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - lines.append((node_geo, circ_edge)) - - for j in range(3): - angle = j * 2 * math.pi / 3 - rotated_verts = [] - for vertex in verts: - # Calculate the vector from the center of the hub to the vertex - x_diff = vertex[0] - mid_midcirc[0] - y_diff = vertex[1] - mid_midcirc[1] - - # Rotate the vector by the desired angle - rotated_x = x_diff * math.cos(angle) - y_diff * math.sin(angle) - rotated_y = x_diff * math.sin(angle) + y_diff * math.cos(angle) - - # Calculate the coordinates of the rotated vertex - rotated_vertex = [mid_midcirc[0] + rotated_x, mid_midcirc[1] + rotated_y] - - rotated_verts.append(rotated_vertex) - - rotated_patch = PathPatch(mpath.Path(rotated_verts, codes), fc="k", ec="none") - - polys.append(rotated_patch) - - polys.append(Circle(mid_midcirc, hub_size, fc="k", ec=edgecolors[i])) # Center hub - - if len(unique_angles) != 0 and "PV" in unique_angles[i]["sgen"] or patch_type=="PV": - angle = unique_angles[i]["sgen"]["PV"] + (angles[i] or 0) or angles[i] - - mid_rect = node_geo + _rotate_dim2(np.array([0, 2 * size]), angle) - rect_lbottom = [mid_rect[0] - (pv_rect_size / 4), mid_rect[1]] - pv_patch = Rectangle((rect_lbottom), pv_rect_size / 2, pv_rect_size, angle=-angle * (180 / np.pi), - rotation_point=(mid_rect[0], mid_rect[1]), ec="k", fc="none") - polys.append(pv_patch) - lines.append((node_geo, mid_rect)) - triangle_base = pv_tri_size - triangle_height = pv_tri_size * 0.75 - triangle_points = [ - (mid_rect + _rotate_dim2(np.array([- triangle_base / 2, + 2 * size]), angle)), - (mid_rect + _rotate_dim2(np.array([+ triangle_base / 2, + 2 * size]), angle)), - (mid_rect + _rotate_dim2(np.array([0, + 1.5 * triangle_height]), angle)), - ] - triangle_patch = Polygon(triangle_points, ec="k", fc="none") - polys.append(triangle_patch) - - if len(unique_angles) != 0 and "wye" in unique_angles[i]["sgen"] or patch_type=="wye": - angle = unique_angles[i]["sgen"]["wye"] + (angles[i] or 0) or angles[i] - - mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angle) - circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angle) - mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angle) - mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angle) - # dropped perpendicular foot of triangle1 - perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angle) - line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2.5 * r_triangle, 0]), angle) - perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angle) - line_end2 = perp_foot2 + + _rotate_dim2(np.array([2.5 * r_triangle, 0]), angle) - polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, - orientation=-angle, fc=facecolors[i], ec=edgecolors[i])) - polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, - orientation=np.pi - angle, fc=facecolors[i], - ec=edgecolors[i])) - lines.append((node_geo, circ_edge)) - lines.append((perp_foot1, line_end1)) - lines.append((perp_foot2, line_end2)) - if len(unique_angles) == 0 : - mid_circ = node_geo + _rotate_dim2(np.array([0, offset + size]), angles[i]) - circ_edge = node_geo + _rotate_dim2(np.array([0, offset]), angles[i]) - mid_tri1 = mid_circ + _rotate_dim2(np.array([r_triangle, -r_triangle / 4]), angles[i]) - mid_tri2 = mid_circ + _rotate_dim2(np.array([-r_triangle, r_triangle / 4]), angles[i]) - # dropped perpendicular foot of triangle1 - perp_foot1 = mid_tri1 + _rotate_dim2(np.array([0, -r_triangle / 2]), angles[i]) - line_end1 = perp_foot1 + + _rotate_dim2(np.array([-2.5 * r_triangle, 0]), angles[i]) - perp_foot2 = mid_tri2 + _rotate_dim2(np.array([0, r_triangle / 2]), angles[i]) - line_end2 = perp_foot2 + + _rotate_dim2(np.array([2.5 * r_triangle, 0]), angles[i]) - polys.append(Circle(mid_circ, size, fc=facecolors[i], ec=edgecolors[i])) - polys.append(RegularPolygon(mid_tri1, numVertices=3, radius=r_triangle, - orientation=-angles[i], fc=facecolors[i], ec=edgecolors[i])) - polys.append(RegularPolygon(mid_tri2, numVertices=3, radius=r_triangle, - orientation=np.pi - angles[i], fc=facecolors[i], - ec=edgecolors[i])) - lines.append((node_geo, circ_edge)) - lines.append((perp_foot1, line_end1)) - lines.append((perp_foot2, line_end2)) + if draw_sgens_by_type: + if len(unique_angles) != 0 and "WT" in unique_angles[i]["sgen"] or patch_type=="WT": + angle = (unique_angles[i]["sgen"]["WT"] + (angles[i] or 0)) or angles[i] + wt_patch(node_geo, offset, size, angle, polys, lines, facecolors, edgecolors, blade_coord1, blade_coord2,hub_size, Path, i) + + if len(unique_angles) != 0 and "PV" in unique_angles[i]["sgen"] or patch_type=="PV": + angle = unique_angles[i]["sgen"]["PV"] + (angles[i] or 0) or angles[i] + pv_patch(node_geo, offset, size, angle, pv_rect_size,pv_tri_size, polys,lines, facecolors, edgecolors,i) + + if len(unique_angles) != 0 and "wye" in unique_angles[i]["sgen"] or patch_type=="wye" : + angle = unique_angles[i]["sgen"]["wye"] + (angles[i] or 0) or angles[i] + wye_patch(node_geo, offset, size, r_triangle, angle,polys,lines, facecolors, edgecolors,i) + if len(unique_angles) == 0 : + wye_patch(node_geo, offset, size, r_triangle, angle,polys,lines, facecolors, edgecolors,i) + else: + continue else: - continue + for x in range(len(unique_angles[i]["sgen"])): + angle = list(unique_angles[i]["sgen"].values())[x] + wye_patch(node_geo, offset, size, r_triangle, angle,polys,lines, facecolors, edgecolors,i) return lines, polys, {"offset", "r_triangle", "patch_edgecolor", "patch_facecolor"} From c6addd89491abf3cd1340d67d527e2ae169294cc Mon Sep 17 00:00:00 2001 From: hzraja Date: Wed, 20 Dec 2023 19:02:35 +0100 Subject: [PATCH 30/33] removed redundancies --- pandapower/plotting/collections.py | 13 ++- pandapower/plotting/patch_makers.py | 16 ++-- pandapower/plotting/simple_plot.py | 143 ++++++---------------------- 3 files changed, 45 insertions(+), 127 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index f786b8bce..4edeecdcb 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -997,8 +997,8 @@ def create_load_collection(net, loads=None, size=1., infofunc=None, orientation= """ from pandapower.plotting.simple_plot import calculate_unique_angles - if unique_angles == None: - unique_angles = calculate_unique_angles(net) + # if unique_angles == None: + # unique_angles = calculate_unique_angles(net) loads = get_index_array(loads, net.load.index) infos = [infofunc(i) for i in range(len(loads))] if infofunc is not None else [] node_coords = net.bus_geodata.loc[:, ["x", "y"]].values @@ -1041,8 +1041,8 @@ def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=N """ from pandapower.plotting.simple_plot import calculate_unique_angles - if unique_angles == None: - unique_angles = calculate_unique_angles(net) + # if unique_angles == None: + # unique_angles = calculate_unique_angles(net) gens = get_index_array(gens, net.gen.index) infos = [infofunc(i) for i in range(len(gens))] if infofunc is not None else [] node_coords = net.bus_geodata.loc[:, ["x", "y"]].values @@ -1082,9 +1082,8 @@ def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation **sgen_lc** - line collection """ from pandapower.plotting.simple_plot import calculate_unique_angles - - if unique_angles == None: - unique_angles = calculate_unique_angles(net) + # if draw_sgens_by_type == True: + # unique_angles = calculate_unique_angles(net) infos = [infofunc(i) for i in range(len(sgens))] if infofunc is not None else [] diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index 48e15a756..e2161e2f9 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -394,7 +394,7 @@ def sgen_patches(node_coords, size, angles,patch_type, unique_angles,draw_sgens_ unique_angles = {} for i, node_geo in enumerate(node_coords): - if draw_sgens_by_type: + if draw_sgens_by_type or draw_sgens_by_type==None: if len(unique_angles) != 0 and "WT" in unique_angles[i]["sgen"] or patch_type=="WT": angle = (unique_angles[i]["sgen"]["WT"] + (angles[i] or 0)) or angles[i] wt_patch(node_geo, offset, size, angle, polys, lines, facecolors, edgecolors, blade_coord1, blade_coord2,hub_size, Path, i) @@ -407,13 +407,17 @@ def sgen_patches(node_coords, size, angles,patch_type, unique_angles,draw_sgens_ angle = unique_angles[i]["sgen"]["wye"] + (angles[i] or 0) or angles[i] wye_patch(node_geo, offset, size, r_triangle, angle,polys,lines, facecolors, edgecolors,i) if len(unique_angles) == 0 : + angle = angles[i] wye_patch(node_geo, offset, size, r_triangle, angle,polys,lines, facecolors, edgecolors,i) + + elif draw_sgens_by_type == False or unique_angles == {}: + if unique_angles == {}: + angle = angles[i] + wye_patch(node_geo, offset, size, r_triangle, angle, polys, lines, facecolors, edgecolors, i) else: - continue - else: - for x in range(len(unique_angles[i]["sgen"])): - angle = list(unique_angles[i]["sgen"].values())[x] - wye_patch(node_geo, offset, size, r_triangle, angle,polys,lines, facecolors, edgecolors,i) + for x in range(len(unique_angles[i]["sgen"])): + angle = list(unique_angles[i]["sgen"].values())[x] + wye_patch(node_geo, offset, size, r_triangle, angle,polys,lines, facecolors, edgecolors,i) return lines, polys, {"offset", "r_triangle", "patch_edgecolor", "patch_facecolor"} diff --git a/pandapower/plotting/simple_plot.py b/pandapower/plotting/simple_plot.py index 36c45bda7..a4fc8d36b 100644 --- a/pandapower/plotting/simple_plot.py +++ b/pandapower/plotting/simple_plot.py @@ -30,9 +30,9 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_grid_size=1.0, trafo_size=1.0, plot_loads=False, plot_gens=False, plot_sgens=False, orientation=None, load_size=1.0, gen_size=1.0, sgen_size=1.0, - switch_size=2.0, switch_distance=1.0, plot_line_switches=False, scale_size=True, additional_patches=None, + switch_size=2.0, switch_distance=1.0, plot_line_switches=False, scale_size=True, bus_color='b', line_color='grey', dcline_color='c', trafo_color='k', - ext_grid_color='y', switch_color='k', library='igraph', show_plot=True, ax=None): + ext_grid_color='y', switch_color='k', library='igraph', show_plot=True, ax=None, draw_sgens_by_type=None): """ Plots a pandapower network as simple as possible. If no geodata is available, artificial geodata is generated. For advanced plotting see the tutorial @@ -176,120 +176,35 @@ def simple_plot(net, respect_switches=False, line_width=1.0, bus_size=1.0, ext_g net, size=switch_size, distance_to_bus=switch_distance, use_line_geodata=not use_bus_geodata, zorder=12, color=switch_color) collections.append(sc) - if additional_patches: - patch_count_unique = {} - sgen_types = {} - - for index, bus in enumerate(net.bus_geodata.index): - sgen_count = 0 - gen_count = 0 - load_count = 0 - if plot_sgens and len(net.sgen): - sgen_types_counts = net.sgen[net.sgen.bus == index].type.value_counts() - PV = sgen_types_counts.get("PV", 0) - WT = sgen_types_counts.get("WT", 0) - WYE = sum(sgen_types_counts) - PV - WT - types = {} - if PV: - types["PV"] = PV - - if WT: - types["WT"] = WT - - if WYE: - types["wye"] = WYE - sgen_types[index] = types - - if index not in patch_count_unique: - patch_count_unique[index] = {} - try: - sgen_count = len(sgen_types[index]) - except KeyError: - sgen_count = 0 - - if plot_gens and len(net.gen): - try: - gen_count = len(pp.get_connected_elements_dict(net, element_types=["gen"], buses=index)) - except KeyError: - gen_count = 0 - - if plot_loads and len(net.load): - try: - load_count = len(pp.get_connected_elements_dict(net, element_types=["load"], buses=index)) - except KeyError: - load_count = 0 - total_count = sgen_count + gen_count + load_count - try: seperation_angle = 2 * math.pi / total_count - except ZeroDivisionError: seperation_angle = None - - if plot_sgens and len(net.sgen): - patch_count_unique[index]['sgen'] = dict( - zip(sgen_types[index].keys(), [j * seperation_angle for j in range(sgen_count)])) - - if plot_gens and len(net.gen): - if index not in patch_count_unique: - patch_count_unique[index] = {} - - if 'gen' not in patch_count_unique[index]: - patch_count_unique[index]['gen'] = [] - patch_count_unique[index]['gen'].extend( - [j * seperation_angle + sgen_count * seperation_angle for j in range(gen_count)]) - - if plot_loads and len(net.load): - if index not in patch_count_unique: - patch_count_unique[index] = {} - - if 'load' not in patch_count_unique[index]: - patch_count_unique[index]['load'] = [] - patch_count_unique[index]['load'].extend( - [j * seperation_angle + (sgen_count + gen_count) * seperation_angle for j in range(load_count)]) - if plot_sgens and len(net.sgen): - sgc = create_sgen_collection(net, size=sgen_size, orientation=orientation, unique_angles=patch_count_unique) - collections.append(sgc) - - if plot_gens and len(net.gen): - gc = create_gen_collection(net, size=gen_size, orientation=orientation, unique_angles=patch_count_unique) - collections.append(gc) - - if plot_loads and len(net.load): - lc = create_load_collection(net, size=load_size, orientation=orientation, unique_angles=patch_count_unique) - collections.append(lc) - - if len(net.switch): - bsc = create_bus_bus_switch_collection(net, size=switch_size) - collections.append(bsc) - - ax = draw_collections(collections, ax=ax) - if show_plot: - if not MATPLOTLIB_INSTALLED: - soft_dependency_error(str(sys._getframe().f_code.co_name) + "()", "matplotlib") - plt.show() - return ax + if draw_sgens_by_type: + angles = calculate_unique_angles(net) else: - - if plot_sgens and len(net.sgen): - sgc = create_sgen_collection(net, size=sgen_size, orientation=orientation) - collections.append(sgc) - - if plot_gens and len(net.gen): - gc = create_gen_collection(net, size=gen_size, orientation=orientation) - collections.append(gc) - - if plot_loads and len(net.load): - lc = create_load_collection(net, size=load_size, orientation=orientation) - collections.append(lc) - - if len(net.switch): - bsc = create_bus_bus_switch_collection(net, size=switch_size) - collections.append(bsc) - - ax = draw_collections(collections, ax=ax) - if show_plot: - if not MATPLOTLIB_INSTALLED: - soft_dependency_error(str(sys._getframe().f_code.co_name) + "()", "matplotlib") - plt.show() - return ax + angles = None + + if plot_sgens and len(net.sgen): + sgc = create_sgen_collection(net, size=sgen_size, orientation=orientation, unique_angles=angles, + draw_sgens_by_type=draw_sgens_by_type) + collections.append(sgc) + + if plot_gens and len(net.gen): + gc = create_gen_collection(net, size=gen_size, orientation=orientation, unique_angles=angles) + collections.append(gc) + + if plot_loads and len(net.load): + lc = create_load_collection(net, size=load_size, orientation=orientation, unique_angles=angles) + collections.append(lc) + + if len(net.switch): + bsc = create_bus_bus_switch_collection(net, size=switch_size) + collections.append(bsc) + + ax = draw_collections(collections, ax=ax) + if show_plot: + if not MATPLOTLIB_INSTALLED: + soft_dependency_error(str(sys._getframe().f_code.co_name) + "()", "matplotlib") + plt.show() + return ax def calculate_unique_angles(net): patch_count_unique = {} From 9a551530331c2e74f8835bf37819d2430b78754f Mon Sep 17 00:00:00 2001 From: hzraja Date: Mon, 8 Jan 2024 18:49:50 +0100 Subject: [PATCH 31/33] removed main.py --- main.py | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 main.py diff --git a/main.py b/main.py deleted file mode 100644 index b69ac6407..000000000 --- a/main.py +++ /dev/null @@ -1,37 +0,0 @@ -import matplotlib -import matplotlib.pyplot as plt - -from copy import deepcopy -import pandapower as pp -import pandapower.plotting as plot -from pandapower import networks as nw -from pandapower.networks import example_simple -from IPython.display import display, Markdown - -net = nw.mv_oberrhein() -pp.create_sgens(net, buses=net.bus.index[0:50], p_mw=1, type=["wye"]*50) - -net.sgen.type.loc[0:50] = "WT" -bc = plot.create_bus_collection(net, net.bus.index, size=80, color="red", zorder=1) -# sc= plot.create_sgen_collection(net, sgens=net.sgen.index[0:50], size=80,orientation=0, picker=False) -#sc= plot.create_sgen_collection(net, sgens=net.sgen.index, size=80,orientation=1.4, picker=False, patch_type=["wye", "WT", "PV"]) - -# wind_turbine_sgen = net.sgen.loc[net.sgen.type == "WT"].index -# wt_c = plot.create_sgen_collection(net, sgens=wind_turbine_sgen, size=80, orientation=1.4, picker=False, patch_type="WT") - - -# pc_sgen = net.sgen.loc[net.sgen.type == "PV"].index -# pv_c = plot.create_sgen_collection(net, sgens=pc_sgen, size=80, orientation=1.4, picker=False, patch_type="PV") - - -#todo for simple plot -# orientation_list = [0, 180] -# for type in net.sgen.type.unique(): -# sgen_indices = net.sgen.loc[net.sgen.type == type].index -# s_c = plot.create_sgen_collection(net, sgens=sgen_indices, size=80, orientation="insert angles from your method", picker=False, patch_type=type) -# collections.append(s_c) - -plot.draw_collections([bc], figsize=(8,6)) - -# pp.plotting.simple_plot(net, plot_loads=True, plot_gens=False, plot_sgens=True,orientation=0, load_size=2.5, gen_size=2.0,sgen_size=2,additional_patches=False); - From 354f822a574e161d6d29b2aaab9d929365b0cc1b Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Tue, 9 Apr 2024 10:49:49 +0200 Subject: [PATCH 32/33] align parameter order as in the other collection functions --- pandapower/plotting/collections.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index 67b0521ab..cd9cbe5ac 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -391,7 +391,7 @@ def create_bus_collection(net, buses=None, size=5, patch_type="circle", color=No If None, net["bus_geodata"] is used **cbar_title** (str, "Bus Voltage [pu]") - colormap bar title in case of given cmap - + **clim** (tuple of floats, None) - setting the norm limits for image scaling **plot_colormap** (bool, True) - flag whether the colormap is actually drawn @@ -1122,8 +1122,8 @@ def create_storage_collection(net, storages=None, size=1., infofunc=None, orient return storage_pc, storage_lc -def create_ext_grid_collection(net, size=1., infofunc=None, orientation=0, picker=False, - ext_grids=None, ext_grid_buses=None, **kwargs): +def create_ext_grid_collection(net, ext_grids=None, size=1., infofunc=None, orientation=0, + picker=False, ext_grid_buses=None, **kwargs): """ Creates a matplotlib patch collection of pandapower ext_grid. Parameters ext_grids, ext_grid_buses can be used to specify, which ext_grids the collection should be From 8dc50bd0cdbab928f03f439a3616fa4c50179c2d Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Fri, 12 Apr 2024 08:45:37 +0200 Subject: [PATCH 33/33] * fix number of plotted elements (not at every node a sgen or gen... * PeP8 max line length --- pandapower/plotting/collections.py | 31 +++++++++++++++++------------ pandapower/plotting/patch_makers.py | 2 +- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/pandapower/plotting/collections.py b/pandapower/plotting/collections.py index d6b02d625..465ddb66a 100644 --- a/pandapower/plotting/collections.py +++ b/pandapower/plotting/collections.py @@ -223,7 +223,8 @@ def _create_line2d_collection(coords, indices, infos=None, picker=False, **kwarg def _create_node_element_collection(node_coords, patch_maker, size=1., infos=None, repeat_infos=(1, 1), orientation=np.pi, picker=False, - patch_facecolor="w", patch_edgecolor="k", line_color="k",patch_type=None,unique_angles=None,draw_sgens_by_type=None, + patch_facecolor="w", patch_edgecolor="k", line_color="k", + patch_type=None, unique_angles=None,draw_sgens_by_type=None, **kwargs): """ Creates matplotlib collections of node elements. All node element collections usually consist of @@ -279,8 +280,9 @@ def _create_node_element_collection(node_coords, patch_maker, size=1., infos=Non linewidths = kwargs.pop("linewidth", linewidths) linewidths = kwargs.pop("lw", linewidths) lines, polys, popped_keywords = patch_maker( - node_coords, size, angles,patch_type = patch_type, unique_angles=unique_angles,draw_sgens_by_type=draw_sgens_by_type, patch_facecolor=patch_facecolor, patch_edgecolor=patch_edgecolor, - **kwargs) + node_coords, size, angles, patch_type = patch_type, unique_angles=unique_angles, + draw_sgens_by_type=draw_sgens_by_type, patch_facecolor=patch_facecolor, + patch_edgecolor=patch_edgecolor, **kwargs) for kw in set(popped_keywords) & set(kwargs.keys()): kwargs.pop(kw) patch_coll = PatchCollection(polys, match_original=True, picker=picker, linewidth=linewidths, @@ -966,8 +968,8 @@ def create_busbar_collection(net, buses=None, infofunc=None, cmap=None, norm=Non return lc -def create_load_collection(net, loads=None, size=1., infofunc=None, orientation=None, picker=False, unique_angles=None, - **kwargs): +def create_load_collection(net, loads=None, size=1., infofunc=None, orientation=None, picker=False, + unique_angles=None, **kwargs): """ Creates a matplotlib patch collection of pandapower loads. @@ -1001,7 +1003,7 @@ def create_load_collection(net, loads=None, size=1., infofunc=None, orientation= # unique_angles = calculate_unique_angles(net) loads = get_index_array(loads, net.load.index) infos = [infofunc(i) for i in range(len(loads))] if infofunc is not None else [] - node_coords = net.bus_geodata.loc[:, ["x", "y"]].values + node_coords = net.bus_geodata.loc[net.load.loc[loads, "bus"].values, ["x", "y"]].values color = kwargs.pop("color", "k") @@ -1011,7 +1013,8 @@ def create_load_collection(net, loads=None, size=1., infofunc=None, orientation= return load_pc, load_lc -def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=None, picker=False,unique_angles=None, **kwargs): +def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=None, picker=False, + unique_angles=None, **kwargs): """ Creates a matplotlib patch collection of pandapower gens. @@ -1045,7 +1048,7 @@ def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=N # unique_angles = calculate_unique_angles(net) gens = get_index_array(gens, net.gen.index) infos = [infofunc(i) for i in range(len(gens))] if infofunc is not None else [] - node_coords = net.bus_geodata.loc[:, ["x", "y"]].values + node_coords = net.bus_geodata.loc[net.gen.loc[gens, "bus"].values, ["x", "y"]].values color = kwargs.pop("color", "k") gen_pc, gen_lc = _create_node_element_collection( node_coords, gen_patches, size=size, infos=infos, orientation=orientation, @@ -1053,7 +1056,8 @@ def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=N return gen_pc, gen_lc -def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation=None, picker=False, patch_type=None, unique_angles=None,draw_sgens_by_type=None, **kwargs): +def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation=None, picker=False, + patch_type=None, unique_angles=None,draw_sgens_by_type=None, **kwargs): """ Creates a matplotlib patch collection of pandapower sgen. @@ -1087,7 +1091,7 @@ def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation infos = [infofunc(i) for i in range(len(sgens))] if infofunc is not None else [] - node_coords = net.bus_geodata.loc[:, ["x", "y"]].values + node_coords = net.bus_geodata.loc[net.sgen.loc[sgens, "bus"].values, ["x", "y"]].values color = kwargs.pop("color", "k") sgen_pc, sgen_lc = _create_node_element_collection( node_coords, sgen_patches, size=size, infos=infos, orientation=orientation, @@ -1181,7 +1185,8 @@ def create_ext_grid_collection(net, ext_grids=None, size=1., infofunc=None, orie return ext_grid_pc, ext_grid_lc -def create_line_switch_collection(net, switches=None, size=1, distance_to_bus=3, use_line_geodata=False, **kwargs): +def create_line_switch_collection(net, switches=None, size=1, distance_to_bus=3, + use_line_geodata=False, **kwargs): """ Creates a matplotlib patch collection of pandapower line-bus switches. @@ -1346,8 +1351,8 @@ def create_bus_bus_switch_collection(net, size=1., helper_line_style=':', helper def draw_collections(collections, figsize=(10, 8), ax=None, plot_colorbars=True, set_aspect=True, - axes_visible=(False, False), copy_collections=True, draw=True, aspect=('equal', 'datalim'), - autoscale=(True, True, True)): + axes_visible=(False, False), copy_collections=True, draw=True, + aspect=('equal', 'datalim'), autoscale=(True, True, True)): """ Draws matplotlib collections which can be created with the create collection functions. diff --git a/pandapower/plotting/patch_makers.py b/pandapower/plotting/patch_makers.py index e2161e2f9..ce2778e7f 100644 --- a/pandapower/plotting/patch_makers.py +++ b/pandapower/plotting/patch_makers.py @@ -240,7 +240,6 @@ def polygon_patches(node_coords, radius, num_edges, color=None, **kwargs): return patches - def load_patches(node_coords, size, angles, unique_angles, **kwargs): """ Creation function of patches for loads. @@ -296,6 +295,7 @@ def load_patches(node_coords, size, angles, unique_angles, **kwargs): return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"} + def gen_patches(node_coords, size, angles, unique_angles, **kwargs): """ Creation function of patches for generators.