def rectangle_patches(node_coords, width, height, color=None, **kwargs): """ Function to create a list of rectangle patches from node coordinates. :param node_coords: coordinates of the nodes to draw :type node_coords: iterable :param width: width of the rectangle :type width: float :param height: height of the rectangle :type height: float :param color: color or colors of the patches :type color: iterable, float :param kwargs: additional keyword arguments to pass to the Rectangle initialization :type kwargs: dict :return: patches - list of rectangle patches for the nodes """ if not MATPLOTLIB_INSTALLED: soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", "matplotlib") patches = list() if color is not None: colors = get_color_list(color, len(node_coords)) for (x, y), col in zip(node_coords, colors): patches.append( Rectangle((x - width / 2, y - height / 2), width, height, color=color, **kwargs)) else: for x, y in node_coords: patches.append( Rectangle((x - width / 2, y - height / 2), width, height, **kwargs)) return patches
def ellipse_patches(node_coords, width, height, angle=0, color=None, **kwargs): """ Function to create a list of ellipse patches from node coordinates. :param node_coords: coordinates of the nodes to draw :type node_coords: iterable :param width: width of the ellipse (described by an exterior rectangle) :type width: float :param height: height of the ellipse (described by an exterior rectangle) :type height: float :param angle: angle by which to rotate the ellipse :type angle: float :param color: color or colors of the patches :type color: iterable, float :param kwargs: additional keyword arguments to pass to the Ellipse initialization :type kwargs: dict :return: patches - list of ellipse patches for the nodes """ if not MATPLOTLIB_INSTALLED: soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", "matplotlib") patches = list() angles = get_angle_list(angle, len(node_coords)) if color is not None: colors = get_color_list(color, len(node_coords)) for (x, y), col, ang in zip(node_coords, colors, angles): patches.append( Ellipse((x, y), width, height, angle=ang, color=col, **kwargs)) else: for (x, y), ang in zip(node_coords, angles): patches.append(Ellipse((x, y), width, height, angle=ang, **kwargs)) return patches
def to_excel(net, filename, include_empty_tables=False, include_results=True): """ Saves a pandapower Network to an excel file. INPUT: **net** (dict) - The pandapower format network **filename** (string) - The absolute or relative path to the output file OPTIONAL: **include_empty_tables** (bool, False) - empty element tables are saved as excel sheet **include_results** (bool, True) - results are included in the excel sheet EXAMPLE: >>> pp.to_excel(net, os.path.join("C:", "example_folder", "example1.xlsx")) # absolute path >>> pp.to_excel(net, "example2.xlsx") # relative path """ if not xlsxwriter_INSTALLED: soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", "xlsxwriter") writer = pd.ExcelWriter(filename, engine='xlsxwriter') dict_net = io_utils.to_dict_of_dfs( net, include_results=include_results, include_empty_tables=include_empty_tables) for item, table in dict_net.items(): table.to_excel(writer, sheet_name=item) writer.save()
def trafo_patches(coords, size, **kwargs): """ Creates a list of patches and line coordinates representing transformers each connecting two nodes. :param coords: list of connecting node coordinates (usually should be \ `[((x11, y11), (x12, y12)), ((x21, y21), (x22, y22)), ...]`) :type coords: (N, (2, 2)) shaped iterable :param size: size of the trafo patches :type size: float :param kwargs: additional keyword arguments (might contain parameters "patch_edgecolor" and\ "patch_facecolor") :type kwargs: :return: Return values are: \ - lines (list) - list of coordinates for lines connecting nodes and transformer patches\ - circles (list of Circle) - list containing the transformer patches (rings) """ if not MATPLOTLIB_INSTALLED: soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", "matplotlib") edgecolor = kwargs.get("patch_edgecolor", "w") facecolor = kwargs.get("patch_facecolor", (1, 0, 0, 0)) edgecolors = get_color_list(edgecolor, len(coords)) facecolors = get_color_list(facecolor, len(coords)) linewidths = kwargs.get("linewidths", 2.) linewidths = get_linewidth_list(linewidths, len(coords), name_entries="trafos") circles, lines = list(), list() for i, (p1, p2) in enumerate(coords): p1 = np.array(p1) p2 = np.array(p2) if np.all(p1 == p2): continue d = np.sqrt(np.sum((p1 - p2)**2)) if size is None: size_this = np.sqrt(d) / 5 else: size_this = size off = size_this * 0.35 circ1 = (0.5 - off / d) * (p1 - p2) + p2 circ2 = (0.5 + off / d) * (p1 - p2) + p2 circles.append( Circle(circ1, size_this, fc=facecolors[i], ec=edgecolors[i], lw=linewidths[i])) circles.append( Circle(circ2, size_this, fc=facecolors[i], ec=edgecolors[i], lw=linewidths[i])) lp1 = (0.5 - off / d - size_this / d) * (p2 - p1) + p1 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"}
def plot_loading(net, element="line", boxcolor="b", mediancolor="r", whiskercolor="k", ax=None, index_subset=None): if not MATPLOTLIB_INSTALLED: soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", "matplotlib") if ax is None: plt.figure(facecolor="white", dpi=80) ax = plt.gca() if index_subset is None: index_subset = net[element].index loadings = net["res_%s" % element].loading_percent.values[net[ "res_%s" % element].index.isin(index_subset)] boxplot = ax.boxplot(loadings[~np.isnan(loadings)], whis=[0, 100]) for l in list(boxplot.keys()): plt.setp(boxplot[l], lw=3) if l == "medians": plt.setp(boxplot[l], color=mediancolor) elif l == "boxes" or l == "whiskers": plt.setp(boxplot[l], color=boxcolor) else: plt.setp(boxplot[l], color=whiskercolor)
def get_plotly_color_palette(n): if not MATPLOTLIB_INSTALLED: soft_dependency_error(str(sys._getframe().f_code.co_name)+"()", "matplotlib") if 'seaborn' in sys.modules: return _to_plotly_palette(seaborn.color_palette("hls", n)) else: hsv = plt.get_cmap('hsv') return _to_plotly_palette(hsv(np.linspace(0, 1.0, n)))
def get_plotly_color(color_string): if not MATPLOTLIB_INSTALLED: soft_dependency_error(str(sys._getframe().f_code.co_name)+"()", "matplotlib") try: converted = _to_plotly_color(mplc.to_rgba(color_string)) return converted except ValueError: return color_string
def _branch_geometries_from_geodata(branch_geo, epsg=31467): missing_packages = array(["shapely", "geopandas"])[~array([ shapely_INSTALLED, geopandas_INSTALLED])] if len(missing_packages): soft_dependency_error(str(sys._getframe().f_code.co_name)+"()", missing_packages) geoms = GeoSeries([LineString(x) for x in branch_geo.coords.values], index=branch_geo.index, crs=f"epsg:{epsg}") return GeoDataFrame(branch_geo, crs=f"epsg:{epsg}", geometry=geoms, index=branch_geo.index)
def plot_characteristic(characteristic, start, stop, num=20, xlabel=None, ylabel=None): if not MATPLOTLIB_INSTALLED: soft_dependency_error(str(sys._getframe().f_code.co_name) + "()", "matplotlib") x = np.linspace(start, stop, num) y = characteristic(x) plt.plot(x, y, marker='x') if xlabel is not None: plt.xlabel(xlabel) if ylabel is not None: plt.ylabel(ylabel)
def create_generic_coordinates(net, mg=None, library="igraph", respect_switches=False, geodata_table="bus_geodata", buses=None, overwrite=False): """ This function will add arbitrary geo-coordinates for all buses based on an analysis of branches and rings. It will remove out of service buses/lines from the net. The coordinates will be created either by igraph or by using networkx library. :param net: pandapower network :type net: pandapowerNet :param mg: Existing networkx multigraph, if available. Convenience to save computation time. :type mg: networkx.Graph :param library: "igraph" to use igraph package or "networkx" to use networkx package :type library: str :param geodata_table: table to write the generic geodatas to :type geodata_table: str :param buses: buses for which generic geodata are created, all buses will be used by default :type buses: list :param overwrite: overwrite existing geodata :type overwrite: bool :return: net - pandapower network with added geo coordinates for the buses :Example: net = create_generic_coordinates(net) """ _prepare_geodata_table(net, geodata_table, overwrite) if library == "igraph": if not IGRAPH_INSTALLED: soft_dependency_error("build_igraph_from_pp()", "python-igraph") graph, meshed, roots = build_igraph_from_pp(net, respect_switches, buses=buses) coords = coords_from_igraph(graph, roots, meshed) elif library == "networkx": if mg is None: nxg = top.create_nxgraph(net, respect_switches=respect_switches, include_out_of_service=True) else: nxg = copy.deepcopy(mg) coords = coords_from_nxgraph(nxg) else: raise ValueError("Unknown library %s - chose 'igraph' or 'networkx'" % library) if len(coords): net[geodata_table].x = coords[1] net[geodata_table].y = coords[0] net[geodata_table].index = net.bus.index if buses is None else buses return net
def get_plotly_cmap(values, cmap_name='jet', cmin=None, cmax=None): if not MATPLOTLIB_INSTALLED: soft_dependency_error(str(sys._getframe().f_code.co_name)+"()", "matplotlib") cmap = cm.get_cmap(cmap_name) if cmin is None: cmin = values.min() if cmax is None: cmax = values.max() norm = mplc.Normalize(vmin=cmin, vmax=cmax) bus_fill_colors_rgba = cmap(norm(values).data)[:, 0:3] * 255. return ['rgb({0},{1},{2})'.format(r, g, b) for r, g, b in bus_fill_colors_rgba]
def _to_plotly_color(scl, transparence=None): """ converts a rgb color in format (0-1,0-1,0-1) to a plotly color 'rgb(0-255,0-255,0-255)' """ if not MATPLOTLIB_INSTALLED: soft_dependency_error(str(sys._getframe().f_code.co_name)+"()", "matplotlib") plotly_col = [255 * _c for _c in mplc.to_rgba(scl)] if len(scl) == 3 else [255 * _c for _c in mplc.to_rgb(scl)] if transparence is not None: assert 0. <= transparence <= 1.0 plotly_col[3] = transparence return "rgba({:.0f}, {:.0f}, {:.0f}, {:.4f})".format(*plotly_col) else: return "rgb({:.0f}, {:.0f}, {:.0f})".format(*plotly_col[:3])
def gen_patches(node_coords, size, angles, **kwargs): """ Creation function of patches for generators. :param node_coords: coordinates of the nodes that the generators belong to. :type node_coords: iterable :param size: size of the patch :type size: float :param angles: angles by which to rotate the patches (in radians) :type angles: iterable(float), float :param kwargs: additional keyword arguments (might contain parameters "offset",\ "patch_edgecolor" and "patch_facecolor") :type kwargs: :return: Return values are: \ - lines (list) - list of coordinates for lines leading to generator patches\ - polys (list of RegularPolygon) - list containing the generator patches\ - keywords (set) - set of keywords removed from kwargs """ if not MATPLOTLIB_INSTALLED: soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", "matplotlib") polys, lines = list(), list() offset = kwargs.get("offset", 2. * size) all_angles = get_angle_list(angles, len(node_coords)) edgecolor = kwargs.get("patch_edgecolor", "k") 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)) for i, node_geo in enumerate(node_coords): p2 = node_geo + _rotate_dim2(np.array([0, size + offset]), all_angles[i]) 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, p2 + _rotate_dim2(np.array([0, size]), -all_angles[i]))) return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"}
def _node_geometries_from_geodata(node_geo, epsg=31467): """ Creates a geopandas geodataframe from a given dataframe of with node coordinates as x and y values. :param node_geo: The dataframe containing the node coordinates (x and y values) :type node_geo: pandas.dataframe :param epsg: The epsg projection of the node coordinates :type epsg: int, default 31467 (= Gauss-Krüger Zone 3) :return: node_geodata - a geodataframe containing the node_geo and Points in the geometry column """ missing_packages = array(["shapely", "geopandas"])[~array([ shapely_INSTALLED, geopandas_INSTALLED])] if len(missing_packages): soft_dependency_error(str(sys._getframe().f_code.co_name)+"()", missing_packages) geoms = [Point(x, y) for x, y in node_geo[["x", "y"]].values] return GeoDataFrame(node_geo, crs=f"epsg:{epsg}", geometry=geoms, index=node_geo.index)
def decrypt_string(s, key): missing_packages = numpy.array([ "cryptography", "hashlib", "base64" ])[~numpy. array([cryptography_INSTALLED, hashlib_INSTALLED, base64_INSTALLED])] if len(missing_packages): soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", missing_packages) key_base = hashlib.sha256(key.encode()) key = base64.urlsafe_b64encode(key_base.digest()) cipher_suite = Fernet(key) s = s.encode() s = cipher_suite.decrypt(s) if zlib_INSTALLED: s = zlib.decompress(s) s = s.decode() return s
def _to_plotly_palette(scl, transparence=None): """ converts a rgb color palette in format (0-1,0-1,0-1) to a plotly color palette 'rgb(0-255,0-255,0-255)' """ if not MATPLOTLIB_INSTALLED: soft_dependency_error(str(sys._getframe().f_code.co_name)+"()", "matplotlib") _out = [] for color in scl: plotly_col = [255 * _c for _c in mplc.to_rgba(color)] if transparence: assert 0. <= transparence <= 1.0 plotly_col[3] = transparence plotly_col = "rgba({:.0f}, {:.0f}, {:.0f}, {:.4f})".format(*plotly_col) else: plotly_col = "rgb({:.0f}, {:.0f}, {:.0f})".format(*plotly_col[:3]) _out.append(plotly_col) return _out
def _convert_xy_epsg(x, y, epsg_in=4326, epsg_out=31467): """ Converts the given x and y coordinates according to the defined epsg projections. :param x: x-values of coordinates :type x: iterable :param y: y-values of coordinates :type y: iterable :param epsg_in: current epsg projection :type epsg_in: int, default 4326 (= WGS84) :param epsg_out: epsg projection to be transformed to :type epsg_out: int, default 31467 (= Gauss-Krüger Zone 3) :return: transformed_coords - x and y values in new coordinate system """ if not pyproj_INSTALLED: soft_dependency_error(str(sys._getframe().f_code.co_name)+"()", "pyproj") in_proj = Proj(init='epsg:%i' % epsg_in) out_proj = Proj(init='epsg:%i' % epsg_out) return transform(in_proj, out_proj, x, y)
def from_excel(filename, convert=True): """ Load a pandapower network from an excel file INPUT: **filename** (string) - The absolute or relative path to the input file. **convert** (bool, True) - If True, converts the format of the net loaded from excel from the older version of pandapower to the newer version format OUTPUT: **net** (dict) - The pandapower format network EXAMPLE: >>> net1 = pp.from_excel(os.path.join("C:", "example_folder", "example1.xlsx")) >>> net2 = pp.from_excel("example2.xlsx") #relative path """ if not os.path.isfile(filename): raise UserWarning("File %s does not exist!" % filename) pd_version = version.parse(pd.__version__) if pd_version < version.parse("0.21"): xls = pd.ExcelFile(filename).parse(sheetname=None) elif pd_version < version.parse("0.24"): xls = pd.ExcelFile(filename).parse(sheet_name=None) else: if not openpyxl_INSTALLED: soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", "openpyxl") xls = pd.read_excel(filename, sheet_name=None, index_col=0, engine="openpyxl") try: net = io_utils.from_dict_of_dfs(xls) except: net = _from_excel_old(xls) if convert: convert_format(net) return net
def load_patches(node_coords, size, angles, **kwargs): """ Creation function of patches for loads. :param node_coords: coordinates of the nodes that the loads belong to. :type node_coords: iterable :param size: size of the patch :type size: float :param angles: angles by which to rotate the patches (in radians) :type angles: iterable(float), float :param kwargs: additional keyword arguments (might contain parameters "offset",\ "patch_edgecolor" and "patch_facecolor") :type kwargs: :return: Return values are: \ - lines (list) - list of coordinates for lines leading to load patches\ - polys (list of RegularPolygon) - list containing the load patches\ - keywords (set) - set of keywords removed from kwargs """ if not MATPLOTLIB_INSTALLED: soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", "matplotlib") offset = kwargs.get("offset", 1.2 * size) all_angles = get_angle_list(angles, len(node_coords)) 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)) 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], fc=facecolors[i], ec=edgecolors[i])) lines.append((node_geo, p3)) return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"}
def polygon_patches(node_coords, radius, num_edges, color=None, **kwargs): """ Function to create a list of polygon patches from node coordinates. The number of edges for the polygon can be defined. :param node_coords: coordinates of the nodes to draw :type node_coords: iterable :param radius: radius for the polygon (from centroid to edges) :type radius: float :param num_edges: number of edges of the polygon :type num_edges: int :param color: color or colors of the patches :type color: iterable, float :param kwargs: additional keyword arguments to pass to the Polygon initialization :type kwargs: dict :return: patches - list of rectangle patches for the nodes """ if not MATPLOTLIB_INSTALLED: soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", "matplotlib") patches = list() if color is not None: colors = get_color_list(color, len(node_coords)) for (x, y), col in zip(node_coords, colors): patches.append( RegularPolygon([x, y], numVertices=num_edges, radius=radius, color=color, **kwargs)) else: for x, y in node_coords: patches.append( RegularPolygon([x, y], numVertices=num_edges, radius=radius, **kwargs)) return patches
def plot_voltage_profile(net, plot_transformers=True, ax=None, xlabel="Distance from Slack [km]", ylabel="Voltage [pu]", x0=0, trafocolor="r", bus_colors=None, line_loading_weight=False, voltage_column=None, bus_size=3, lines=None, **kwargs): if not MATPLOTLIB_INSTALLED: soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", "matplotlib") if ax is None: plt.figure(facecolor="white", dpi=120) ax = plt.gca() if not net.converged: raise ValueError("no results in this pandapower network") if voltage_column is None: voltage_column = net.res_bus.vm_pu if lines is None: lines = net.line.index for eg in net.ext_grid[net.ext_grid.in_service == True].bus: d = top.calc_distance_to_bus(net, eg) for lix, line in net.line[(net.line.in_service == True) & net.line.index.isin(lines)].iterrows(): if line.from_bus not in d.index: continue if not ((net.switch.element == line.name) & ~net.switch.closed & (net.switch.et == 'l')).any(): from_bus = line.from_bus to_bus = line.to_bus x = [x0 + d.at[from_bus], x0 + d.at[to_bus]] try: y = [ voltage_column.at[from_bus], voltage_column.at[to_bus] ] except: raise UserWarning if "linewidth" in kwargs or not line_loading_weight: ax.plot(x, y, **kwargs) else: ax.plot(x, y, linewidth=0.4 * np.sqrt(net.res_line.loading_percent.at[lix]), **kwargs) if bus_colors is not None: for bus, x, y in zip((from_bus, to_bus), x, y): if bus in bus_colors: ax.plot(x, y, 'or', color=bus_colors[bus], ms=bus_size) kwargs = {k: v for k, v in kwargs.items() if not k == "label"} # if plot_transformers: # if hasattr(plot_transformers, "__iter__"): # if is a list for example # transformers = net.trafo.loc[list(plot_transformers)] # else: # transformers = net.trafo[net.trafo.in_service == True] # for _, transformer in transformers.iterrows(): # if transformer.hv_bus not in d.index: # continue # ax.plot([x0 + d.loc[transformer.hv_bus], # x0 + d.loc[transformer.lv_bus]], # [voltage_column.loc[transformer.hv_bus], # voltage_column.loc[transformer.lv_bus]], color=trafocolor, # **{k: v for k, v in kwargs.items() if not k == "color"}) # trafo geodata if plot_transformers: for trafo_table in ['trafo', 'trafo3w']: if trafo_table not in net.keys(): continue transformers = net[trafo_table].query('in_service') for tid, tr in transformers.iterrows(): t_buses = [ tr[b_col] for b_col in ('lv_bus', 'mv_bus', 'hv_bus') if b_col in tr.index ] if any([ b not in d.index.values or b not in net.res_bus.index.values for b in t_buses ]): # logger.info('cannot add trafo %d to plot' % tid) continue for bi, bj in combinations(t_buses, 2): tr_coords = ([x0 + d.loc[bi], x0 + d.loc[bj]], [ net.res_bus.at[bi, 'vm_pu'], net.res_bus.at[bj, 'vm_pu'] ]) ax.plot(*tr_coords, color=trafocolor, **{ k: v for k, v in kwargs.items() if not k == "color" }) if xlabel: ax.set_xlabel(xlabel, fontweight="bold", color=(.4, .4, .4)) if ylabel: ax.set_ylabel(ylabel, fontweight="bold", color=(.4, .4, .4)) return ax
def build_igraph_from_pp(net, respect_switches=False, buses=None): """ This function uses the igraph library to create an igraph graph for a given pandapower network. Lines, transformers and switches are respected. Performance vs. networkx: https://graph-tool.skewed.de/performance :param net: pandapower network :type net: pandapowerNet :param respect_switches: if True, exclude edges for open switches (also lines that are \ connected via line switches) :type respect_switches: bool, default False :Example: graph, meshed, roots = build_igraph_from_pp(net) """ if not IGRAPH_INSTALLED: soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", "python-igraph") g = igraph.Graph(directed=True) bus_index = net.bus.index if buses is None else np.array(buses) nr_buses = len(bus_index) g.add_vertices(nr_buses) # g.vs["label"] = [s.encode('unicode-escape') for s in net.bus.name.tolist()] g.vs["label"] = list(bus_index) pp_bus_mapping = dict(list(zip(bus_index, list(range(nr_buses))))) if respect_switches: open_switches = ~net.switch.closed.values.astype(bool) # add lines mask = _get_element_mask_from_nodes(net, "line", ["from_bus", "to_bus"], buses) if respect_switches: mask &= _get_switch_mask(net, "line", "l", open_switches) for line in net.line[mask].itertuples(): g.add_edge(pp_bus_mapping[line.from_bus], pp_bus_mapping[line.to_bus], weight=line.length_km) # add trafos mask = _get_element_mask_from_nodes(net, "trafo", ["hv_bus", "lv_bus"], buses) if respect_switches: mask &= _get_switch_mask(net, "trafo", "t", open_switches) for trafo in net.trafo[mask].itertuples(): g.add_edge(pp_bus_mapping[trafo.hv_bus], pp_bus_mapping[trafo.lv_bus], weight=0.01) # add trafo3w mask = _get_element_mask_from_nodes(net, "trafo3w", ["hv_bus", "mv_bus", "lv_bus"], buses) if respect_switches: mask &= _get_switch_mask(net, "trafo3w", "t3", open_switches) for trafo3w in net.trafo3w[mask].itertuples(): g.add_edge(pp_bus_mapping[trafo3w.hv_bus], pp_bus_mapping[trafo3w.lv_bus], weight=0.01) g.add_edge(pp_bus_mapping[trafo3w.hv_bus], pp_bus_mapping[trafo3w.mv_bus], weight=0.01) # add switches mask = net.switch.et.values == "b" if respect_switches: mask &= ~open_switches bus_mask = _get_element_mask_from_nodes(net, "switch", ["element", "bus"], buses) for switch in net.switch[mask & bus_mask].itertuples(): g.add_edge(pp_bus_mapping[switch.element], pp_bus_mapping[switch.bus], weight=0.001) meshed = _igraph_meshed(g) roots = [ pp_bus_mapping[b] for b in net.ext_grid.bus.values if b in bus_index ] return g, meshed, roots # g, (not g.is_dag())
def sgen_patches(node_coords, size, angles, **kwargs): """ Creation function of patches for static generators. :param node_coords: coordinates of the nodes that the static generators belong to. :type node_coords: iterable :param size: size of the patch :type size: float :param angles: angles by which to rotate the patches (in radians) :type angles: iterable(float), float :param kwargs: additional keyword arguments (might contain parameters "offset", "r_triangle",\ "patch_edgecolor" and "patch_facecolor") :type kwargs: :return: Return values are: \ - lines (list) - list of coordinates for lines leading to static generator patches\ - polys (list of RegularPolygon) - list containing the static generator patches\ - keywords (set) - set of keywords removed from kwargs """ if not MATPLOTLIB_INSTALLED: soft_dependency_error( str(sys._getframe().f_code.co_name) + "()", "matplotlib") polys, lines = list(), list() offset = kwargs.get("offset", 2 * size) r_triangle = kwargs.get("r_triangles", size * 0.4) 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)) 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" }