From c34e3a3861e36a955e75f082c7afa8fb4a4a417b Mon Sep 17 00:00:00 2001 From: mcapodif Date: Mon, 18 Nov 2024 09:37:31 +0100 Subject: [PATCH 01/13] added new plot method --- src/pyedb/common/__init__.py | 0 src/pyedb/common/nets.py | 441 ++++++++++++++++++ .../dotnet/edb_core/edb_data/nets_data.py | 8 +- src/pyedb/dotnet/edb_core/nets.py | 369 +-------------- src/pyedb/generic/filesystem.py | 7 +- 5 files changed, 452 insertions(+), 373 deletions(-) create mode 100644 src/pyedb/common/__init__.py create mode 100644 src/pyedb/common/nets.py diff --git a/src/pyedb/common/__init__.py b/src/pyedb/common/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/pyedb/common/nets.py b/src/pyedb/common/nets.py new file mode 100644 index 0000000000..88500e7279 --- /dev/null +++ b/src/pyedb/common/nets.py @@ -0,0 +1,441 @@ +import math +import time + +from pyedb.generic.constants import CSS4_COLORS + +def is_notebook(): + """Check if pyaedt is running in Jupyter or not. + + Returns + ------- + bool + """ + try: + shell = get_ipython().__class__.__name__ + if shell in ["ZMQInteractiveShell"]: # pragma: no cover + return True # Jupyter notebook or qtconsole + else: + return False + except NameError: + return False # Probably standard Python interpreter + + +def is_ipython(): + """Check if pyaedt is running in Jupyter or not. + + Returns + ------- + bool + """ + try: + shell = get_ipython().__class__.__name__ + if shell in ["TerminalInteractiveShell", "SpyderShell"]: + return True # Jupyter notebook or qtconsole + else: # pragma: no cover + return False + except NameError: + return False # Probably standard Python interpreter + +class CommonNets: + def __init__(self, _pedb): + self._pedb = _pedb + + + + def plot( + self, + nets=None, + layers=None, + color_by_net=False, + show_legend=True, + save_plot=None, + outline=None, + size=(6000, 3000), + plot_components=True, + top_view=True, + show=True, + annotate_component_names=True, + plot_vias=False, + **kwargs, + ): + """Plot a Net to Matplotlib 2D Chart. + + Parameters + ---------- + nets : str, list, optional + Name of the net or list of nets to plot. If ``None`` all nets will be plotted. + layers : str, list, optional + Name of the layers to include in the plot. If ``None`` all the signal layers will be considered. + color_by_net : bool, optional + If ``True`` the plot will be colored by net. + If ``False`` the plot will be colored by layer. (default) + show_legend : bool, optional + If ``True`` the legend is shown in the plot. (default) + If ``False`` the legend is not shown. + save_plot : str, optional + If a path is specified the plot will be saved in this location. + If ``save_plot`` is provided, the ``show`` parameter is ignored. + outline : list, optional + List of points of the outline to plot. + size : tuple, int, optional + Image size in pixel (width, height). Default value is ``(6000, 3000)`` + top_view : bool, optional + Whether if use top view or bottom view. Components will be visible only for the highest layer in the view. + plot_components : bool, optional + If ``True`` the components placed on top layer are plotted. + If ``False`` the components are not plotted. (default). + This may impact in the plot computation time. + If nets and/or layers is specified, only the components belonging to the specified nets/layers are plotted. + annotate_component_names: bool, optional + Whether to add the component names to the plot or not. Default is ``True``. + plot_vias : bool, optional + Whether to plot vias (circular and rectangular) or not. This may impact in the plot computation time. + Default is ``False``. + show : bool, optional + Whether to show the plot or not. Default is `True`. + + Returns + ------- + (ax, fig) + Matplotlib ax and figures. + """ + + if "plot_components_on_top" in kwargs and top_view: + plot_components = kwargs["plot_components_on_top"] + if "plot_components_on_bottom" in kwargs and not top_view: + plot_components = kwargs["plot_components_on_bottom"] + + def mirror_poly(poly): + sign = 1 + if not top_view: + sign = -1 + return [[sign * i[0], i[1]] for i in poly] + + import matplotlib.pyplot as plt + + dpi = 100.0 + figsize = (size[0] / dpi, size[1] / dpi) + + fig = plt.figure(figsize=figsize) + ax = fig.add_subplot(1, 1, 1) + from shapely import affinity + from shapely.geometry import ( + LinearRing, + MultiLineString, + MultiPolygon, + Point, + Polygon, + ) + from shapely.plotting import plot_line, plot_polygon + + start_time = time.time() + if not nets: + nets = list(self.nets.keys()) + if isinstance(nets, str): + nets = [nets] + if not layers: + layers = list(self._pedb.stackup.signal_layers.keys()) + if isinstance(layers, str): + layers = [layers] + color_index = 0 + label_colors = {} + if outline: + poly = Polygon(outline) + plot_line(poly.boundary, add_points=False, color=(0.7, 0, 0), linewidth=4) + else: + bbox = self._pedb.hfss.get_layout_bounding_box() + x1 = bbox[0] + x2 = bbox[2] + y1 = bbox[1] + y2 = bbox[3] + p = [(x1, y1), (x1, y2), (x2, y2), (x2, y1), (x1, y1)] + p = mirror_poly(p) + poly = LinearRing(p) + plot_line(poly, add_points=False, color=(0.7, 0, 0), linewidth=4) + layer_colors = {i: k.color for i, k in self._pedb.stackup.layers.items()} + top_layer = list(self._pedb.stackup.signal_layers.keys())[0] + bottom_layer = list(self._pedb.stackup.signal_layers.keys())[-1] + lines = [] + top_comps = [] + bottom_comps = [] + if plot_components: + nc = 0 + + for comp in self._pedb.components.instances.values(): + if not comp.is_enabled: + continue + net_names = comp.nets + if nets and not any([i in nets for i in net_names]): + continue + layer_name = comp.placement_layer + if layer_name not in layers: + continue + if plot_components and top_view and layer_name == top_layer: + component_color = (0 / 255, 0 / 255, 0 / 255) # this is the color used in AEDT + label = "Component on top layer" + label_colors[label] = component_color + elif plot_components and not top_view and layer_name == bottom_layer: + component_color = (41 / 255, 41 / 255, 41 / 255) # 41, 171, 135 + label = "Component on bottom layer" + label_colors[label] = component_color + else: + continue + for pinst in comp.pins.values(): + pdef = pinst.definition + p_b_l = {i: j for i, j in pdef.pad_by_layer.items()} + pinst_net_name = pinst.net_name + if top_view and top_layer in p_b_l and pinst_net_name in nets: + try: + shape = p_b_l[top_layer].shape + if shape.lower() == "circle": + poly = Point(pinst.position) + top_comps.append(poly.buffer(p_b_l[top_layer].parameters_values[0] / 2)) + elif shape.lower() == "rectangle": + px, py = pinst.position + w, h = p_b_l[top_layer].parameters_values + poly = [ + [px - w / 2, py - h / 2], + [px - w / 2, py + h / 2], + [px + w / 2, py + h / 2], + [px + w / 2, py - h / 2], + ] + poly = Polygon(poly) + top_comps.append( + affinity.rotate( + poly, + (float(p_b_l[top_layer].rotation) + pinst.rotation + comp.rotation) + / math.pi + * 180, + ) + ) + except KeyError: + pass + elif not top_view and bottom_layer in p_b_l and pinst.net_name in nets: + try: + shape = p_b_l[bottom_layer].shape + if shape == "Circle": + x, y = pinst.position + poly = Point(-x, y) + bottom_comps.append(poly.buffer(p_b_l[bottom_layer].parameters_values[0] / 2)) + elif shape == "Rectangle": + px, py = pinst.position + w, h = p_b_l[bottom_layer].parameters_values + poly = [ + [px - w / 2, py - h / 2], + [px - w / 2, py + h / 2], + [px + w / 2, py + h / 2], + [px + w / 2, py - h / 2], + ] + poly = Polygon(mirror_poly(poly)) + bottom_comps.append( + affinity.rotate( + poly, + -(float(p_b_l[bottom_layer].rotation) + pinst.rotation + comp.rotation) + / math.pi + * 180, + ) + ) + except KeyError: + pass + cbb = comp.bounding_box + x = [cbb[0], cbb[0], cbb[2], cbb[2]] + y = [cbb[1], cbb[3], cbb[3], cbb[1]] + vertices = [(i, j) for i, j in zip(x, y)] + vertices = mirror_poly(vertices) + poly = Polygon(vertices) + lines.append(poly.boundary) + if annotate_component_names: + font_size = 6 if poly.area < 6e-6 else 10 + ax.annotate( + comp.name, + (poly.centroid.x, poly.centroid.y), + va="center", + ha="center", + color=component_color, + size=font_size, + rotation=comp.rotation * 180 / math.pi, + ) + self._logger.debug("Plotted {} component(s)".format(nc)) + + if top_comps: + ob = MultiPolygon(top_comps) + plot_polygon(ob, add_points=False, ax=ax) + if bottom_comps: + ob = MultiPolygon(bottom_comps) + plot_polygon(ob, add_points=False, ax=ax) + + if lines: + ob = MultiLineString(lines) + plot_line(ob, ax=ax, add_points=False, color=(1, 0, 0), linewidth=1) + + def create_poly(prim, polys, lines): + if prim.is_void: + return + net_name = prim.net_name + layer_name = prim.layer_name + if nets and (net_name not in nets or layer_name not in layers): + return + # if prim.primitive_type == "path": + # line = prim.center_line + # line = mirror_poly(line) + # poly = LineString(line).buffer(prim.width / 2) + # else: + xt, yt = prim.points() + p1 = [(i, j) for i, j in zip(xt[::-1], yt[::-1])] + p1 = mirror_poly(p1) + + holes = [] + for void in prim.voids: + xvt, yvt = void.points(arc_segments=3) + h1 = mirror_poly([(i, j) for i, j in zip(xvt, yvt)]) + holes.append(h1) + poly = Polygon(p1, holes) + if layer_name == "Outline": + if label_colors[label] in lines: + lines.append(poly.boundary) + elif poly: + polys.append(poly) + return + + if color_by_net: + for net in nets: + prims = self._pedb.nets.nets[net].primitives + polys = [] + lines = [] + if net not in nets: + continue + label = "Net " + net + label_colors[label] = list(CSS4_COLORS.keys())[color_index] + color_index += 1 + if color_index >= len(CSS4_COLORS): + color_index = 0 + for prim in prims: + create_poly(prim, polys, lines) + if polys: + ob = MultiPolygon(polys) + plot_polygon( + ob, ax=ax, color=label_colors[label], add_points=False, alpha=0.7, label=label, edgecolor="none" + ) + if lines: + ob = MultiLineString(p) + plot_line(ob, ax=ax, add_points=False, color=label_colors[label], linewidth=1, label=label) + else: + prims_by_layers_dict = {i: j for i, j in self._pedb.modeler.primitives_by_layer.items()} + if not top_view: + prims_by_layers_dict = { + i: prims_by_layers_dict[i] for i in reversed(self._pedb.modeler.primitives_by_layer.keys()) + } + num_layers = len(layers) + delta_alpha = 0.7 / num_layers + alpha = 0.3 + for layer, prims in prims_by_layers_dict.items(): + polys = [] + lines = [] + if layer not in layers: + continue + label = "Layer " + layer + if label not in label_colors: + try: + color = layer_colors[layer] + c = ( + float(color[0] / 255), + float(color[1] / 255), + float(color[2] / 255), + ) + except: + c = list(CSS4_COLORS.keys())[color_index] + color_index += 1 + if color_index >= len(CSS4_COLORS): + color_index = 0 + label_colors[label] = c + for prim in prims: + create_poly(prim, polys, lines) + if polys: + ob = MultiPolygon(polys) + plot_polygon( + ob, + ax=ax, + color=label_colors[label], + add_points=False, + alpha=alpha, + label=label, + edgecolor="none", + ) + if lines: + ob = MultiLineString(p) + plot_line(ob, ax=ax, add_points=False, color=label_colors[label], linewidth=1, label=label) + alpha = alpha + delta_alpha + + if plot_vias: + polys = [] + + for pinst in self._pedb.padstacks.instances.values(): + if pinst.is_pin: + continue + pdef = pinst.definition + p_b_l = {i: j for i, j in pdef.pad_by_layer.items()} + pinst_net_name = pinst.net_name + if top_view and pinst_net_name in nets: + for k in range(len(layers)): + if layers[k] in p_b_l.keys(): + pad_value = p_b_l[layers[k]] + break + elif not top_view and pinst_net_name in nets: + rev_layers = list(reversed(layers)) + for k in range(len(rev_layers)): + if rev_layers[k] in p_b_l.keys(): + pad_value = p_b_l[rev_layers[k]] + break + else: + continue + try: + shape = pad_value.shape + if shape.lower() == "circle": + x, y = pinst.position + if top_view: + poly = Point(pinst.position) + else: + poly = Point(-x, y) + polys.append(poly.buffer(p_b_l[top_layer].parameters_values[0] / 2)) + elif shape.lower() == "rectangle": + px, py = pinst.position + w, h = pad_value.parameters_values + poly = [ + [px - w / 2, py - h / 2], + [px - w / 2, py + h / 2], + [px + w / 2, py + h / 2], + [px + w / 2, py - h / 2], + ] + poly = Polygon(mirror_poly(poly)) + polys.append( + affinity.rotate( + poly, (float(pad_value.rotation) + pinst.rotation + comp.rotation) / math.pi * 180 + ) + ) + except KeyError: + pass + if polys: + ob = MultiPolygon(polys) + plot_polygon(ob, add_points=False, ax=ax, edgecolor="none") + # Hide grid lines + ax.grid(False) + ax.set_axis_off() + # Hide axes ticks + ax.set_xticks([]) + ax.set_yticks([]) + message = "Edb Top View" if top_view else "Edb Bottom View" + plt.title(message, size=20) + if show_legend: + plt.legend(loc="upper left", fontsize="x-large") + end_time = time.time() - start_time + self._logger.info(f"Plot Generation time {round(end_time, 3)}") + if save_plot: + plt.savefig(save_plot) + if show: # pragma: no cover + if is_notebook(): + pass + elif is_ipython() or "PYTEST_CURRENT_TEST" in os.environ: + fig.show() + else: + plt.show() + return fig, ax diff --git a/src/pyedb/dotnet/edb_core/edb_data/nets_data.py b/src/pyedb/dotnet/edb_core/edb_data/nets_data.py index 0671d73f69..f3be0997c1 100644 --- a/src/pyedb/dotnet/edb_core/edb_data/nets_data.py +++ b/src/pyedb/dotnet/edb_core/edb_data/nets_data.py @@ -113,8 +113,9 @@ def plot( show_legend=True, save_plot=None, outline=None, - size=(2000, 1000), + size=(6000, 3000), show=True, + plot_vias=True, ): """Plot a net to Matplotlib 2D chart. @@ -134,6 +135,9 @@ def plot( Image size in pixel (width, height). show : bool, optional Whether to show the plot or not. Default is `True`. + plot_vias : bool, optional + Whether to plot vias or not. It may impact on performances. + Default is `True`. """ return self._app.nets.plot( @@ -144,6 +148,8 @@ def plot( outline=outline, size=size, show=show, + plot_vias=plot_vias, + ) def get_smallest_trace_width(self): diff --git a/src/pyedb/dotnet/edb_core/nets.py b/src/pyedb/dotnet/edb_core/nets.py index e784aca721..a89a04cf8c 100644 --- a/src/pyedb/dotnet/edb_core/nets.py +++ b/src/pyedb/dotnet/edb_core/nets.py @@ -26,6 +26,7 @@ import time import warnings +from pyedb.common.nets import CommonNets from pyedb.dotnet.edb_core.edb_data.nets_data import EDBNetsData from pyedb.generic.constants import CSS4_COLORS from pyedb.generic.general_methods import generate_unique_name @@ -33,7 +34,7 @@ from pyedb.modeler.geometry_operators import GeometryOperators -class EdbNets(object): +class EdbNets(CommonNets): """Manages EDB methods for nets management accessible from `Edb.nets` property. Examples @@ -381,294 +382,6 @@ def _get_points_for_plot(self, my_net_points): # fmt: on return x, y - def get_plot_data( - self, - nets=None, - layers=None, - color_by_net=False, - outline=None, - plot_components_on_top=False, - plot_components_on_bottom=False, - ): - """Return List of points for Matplotlib 2D Chart. - - Parameters - ---------- - nets : str, list, optional - Name of the net or list of nets to plot. If `None` (default value) all nets will be plotted. - layers : str, list, optional - Name of the layers to include in the plot. If `None` all the signal layers will be considered. - color_by_net : bool, optional - If ``True`` the plot will be colored by net. - If ``False`` the plot will be colored by layer. (default) - outline : list, optional - List of points of the outline to plot. - plot_components_on_top : bool, optional - If ``True`` the components placed on top layer are plotted. - If ``False`` the components are not plotted. (default) - If nets and/or layers is specified, only the components belonging to the specified nets/layers are plotted. - plot_components_on_bottom : bool, optional - If ``True`` the components placed on bottom layer are plotted. - If ``False`` the components are not plotted. (default) - If nets and/or layers is specified, only the components belonging to the specified nets/layers are plotted. - - Returns - ------- - List, str: list of data to be used in plot. - In case of remote session it will be returned a string that could be converted \ - to list using ast.literal_eval(). - """ - start_time = time.time() - if not nets: - nets = list(self.nets.keys()) - if isinstance(nets, str): - nets = [nets] - if not layers: - layers = list(self._pedb.stackup.signal_layers.keys()) - if isinstance(layers, str): - layers = [layers] - color_index = 0 - objects_lists = [] - label_colors = {} - n_label = 0 - max_labels = 10 - - if outline: - xt = [i[0] for i in outline] - yt = [i[1] for i in outline] - xc, yc = GeometryOperators.orient_polygon(xt, yt, clockwise=True) - vertices = [(i, j) for i, j in zip(xc, yc)] - codes = [2 for _ in vertices] - codes[0] = 1 - vertices.append((0, 0)) - codes.append(79) - objects_lists.append([vertices, codes, "b", "Outline", 1.0, 1.5, "contour"]) - n_label += 1 - layer_colors = {i: k.color for i, k in self._pedb.stackup.layers.items()} - top_layer = list(self._pedb.stackup.signal_layers.keys())[0] - bottom_layer = list(self._pedb.stackup.signal_layers.keys())[-1] - if plot_components_on_top or plot_components_on_bottom: - nc = 0 - for comp in self._pedb.components.instances.values(): - if not comp.is_enabled: - continue - net_names = comp.nets - if nets and not any([i in nets for i in net_names]): - continue - layer_name = comp.placement_layer - if layer_name not in layers: - continue - if plot_components_on_top and layer_name == top_layer: - component_color = (184 / 255, 115 / 255, 51 / 255) # this is the color used in AEDT - label = "Component on top layer" - elif plot_components_on_bottom and layer_name == bottom_layer: - component_color = (41 / 255, 171 / 255, 135 / 255) # 41, 171, 135 - label = "Component on bottom layer" - else: - continue - cbb = comp.bounding_box - x = [cbb[0], cbb[0], cbb[2], cbb[2]] - y = [cbb[1], cbb[3], cbb[3], cbb[1]] - vertices = [(i, j) for i, j in zip(x, y)] - codes = [2 for _ in vertices] - codes[0] = 1 - vertices.append((0, 0)) - codes.append(79) - if label not in label_colors: - label_colors[label] = component_color - objects_lists.append([vertices, codes, label_colors[label], label, 1.0, 2.0, "contour"]) - n_label += 1 - else: - objects_lists.append([vertices, codes, label_colors[label], None, 1.0, 2.0, "contour"]) - nc += 1 - self._logger.debug("Plotted {} component(s)".format(nc)) - for prim in self._pedb.modeler.primitives: - if prim.is_void: - continue - net_name = prim.net_name - layer_name = prim.layer_name - if nets and (net_name not in nets or layer_name not in layers): - continue - prim_type = prim.primitive_type - if prim_type == "path": - try: - x, y = prim.points() - except ValueError: - x = None - if not x: - continue - create_label = False - if not color_by_net: - label = "Layer " + layer_name - if label not in label_colors: - try: - color = layer_colors[layer_name] - c = ( - float(color[0] / 255), - float(color[1] / 255), - float(color[2] / 255), - ) - except: - c = list(CSS4_COLORS.keys())[color_index] - color_index += 1 - if color_index >= len(CSS4_COLORS): - color_index = 0 - label_colors[label] = c - create_label = True - else: - label = "Net " + net_name - if label not in label_colors: - label_colors[label] = list(CSS4_COLORS.keys())[color_index] - color_index += 1 - if color_index >= len(CSS4_COLORS): - color_index = 0 - create_label = True - - if create_label and n_label <= max_labels: - objects_lists.append([x, y, label_colors[label], label, 0.4, "fill"]) - n_label += 1 - else: - objects_lists.append([x, y, label_colors[label], None, 0.4, "fill"]) - elif prim_type == "polygon": - xt, yt = prim.points() - if not xt: - continue - x, y = GeometryOperators.orient_polygon(xt, yt, clockwise=True) - vertices = [(i, j) for i, j in zip(x, y)] - codes = [2 for _ in vertices] - codes[0] = 1 - vertices.append((0, 0)) - codes.append(79) - - for void in prim.voids: - xvt, yvt = void.points() - if xvt: - xv, yv = GeometryOperators.orient_polygon(xvt, yvt, clockwise=False) - tmpV = [(i, j) for i, j in zip(xv, yv)] - vertices.extend(tmpV) - tmpC = [2 for _ in tmpV] - tmpC[0] = 1 - codes.extend(tmpC) - vertices.append((0, 0)) - codes.append(79) - - create_label = False - if not color_by_net: - label = "Layer " + layer_name - if label not in label_colors: - try: - color = layer_colors[layer_name] - c = ( - float(color[0] / 255), - float(color[1] / 255), - float(color[2] / 255), - ) - except: - c = list(CSS4_COLORS.keys())[color_index] - color_index += 1 - if color_index >= len(CSS4_COLORS): - color_index = 0 - label_colors[label] = c - create_label = True - else: - label = "Net " + net_name - if label not in label_colors: - label_colors[label] = list(CSS4_COLORS.keys())[color_index] - color_index += 1 - if color_index >= len(CSS4_COLORS): - color_index = 0 - create_label = True - - if create_label and n_label <= max_labels: - if layer_name == "Outline": - objects_lists.append([vertices, codes, label_colors[label], label, 1.0, 2.0, "contour"]) - else: - objects_lists.append([vertices, codes, label_colors[label], label, 0.4, "path"]) - n_label += 1 - else: - if layer_name == "Outline": - objects_lists.append([vertices, codes, label_colors[label], None, 1.0, 2.0, "contour"]) - else: - objects_lists.append([vertices, codes, label_colors[label], None, 0.4, "path"]) - elif prim_type == "circle": - x, y = prim.points() - if not x: - continue - create_label = False - if not color_by_net: - label = "Layer " + layer_name - if label not in label_colors: - try: - color = layer_colors[layer_name] - c = ( - float(color[0] / 255), - float(color[1] / 255), - float(color[2] / 255), - ) - except: - c = list(CSS4_COLORS.keys())[color_index] - color_index += 1 - if color_index >= len(CSS4_COLORS): - color_index = 0 - label_colors[label] = c - create_label = True - else: - label = "Net " + net_name - if label not in label_colors: - label_colors[label] = list(CSS4_COLORS.keys())[color_index] - color_index += 1 - if color_index >= len(CSS4_COLORS): - color_index = 0 - create_label = True - - if create_label and n_label <= max_labels: - objects_lists.append([x, y, label_colors[label], label, 0.4, "fill"]) - n_label += 1 - else: - objects_lists.append([x, y, label_colors[label], None, 0.4, "fill"]) - elif prim_type == "rectangle": - x, y = prim.points() - if not x: - continue - create_label = False - if not color_by_net: - label = "Layer " + layer_name - if label not in label_colors: - try: - color = layer_colors[layer_name] - c = ( - float(color[0] / 255), - float(color[1] / 255), - float(color[2] / 255), - ) - except: - c = list(CSS4_COLORS.keys())[color_index] - color_index += 1 - if color_index >= len(CSS4_COLORS): - color_index = 0 - label_colors[label] = c - create_label = True - else: - label = "Net " + net_name - if label not in label_colors: - label_colors[label] = list(CSS4_COLORS.keys())[color_index] - color_index += 1 - if color_index >= len(CSS4_COLORS): - color_index = 0 - create_label = True - - if create_label and n_label <= max_labels: - objects_lists.append([x, y, label_colors[label], label, 0.4, "fill"]) - n_label += 1 - else: - objects_lists.append([x, y, label_colors[label], None, 0.4, "fill"]) - - end_time = time.time() - start_time - self._logger.info("Nets Point Generation time %s seconds", round(end_time, 3)) - if os.getenv("PYAEDT_SERVER_AEDT_PATH", None): - return str(objects_lists) - else: - return objects_lists def classify_nets(self, power_nets=None, signal_nets=None): """Reassign power/ground or signal nets based on list of nets. @@ -701,84 +414,6 @@ def classify_nets(self, power_nets=None, signal_nets=None): self.nets[net].net_object.SetIsPowerGround(False) return True - def plot( - self, - nets=None, - layers=None, - color_by_net=False, - show_legend=True, - save_plot=None, - outline=None, - size=(2000, 1000), - plot_components_on_top=False, - plot_components_on_bottom=False, - show=True, - title=None, - ): - """Plot a Net to Matplotlib 2D Chart. - - Parameters - ---------- - nets : str, list, optional - Name of the net or list of nets to plot. If ``None`` all nets will be plotted. - layers : str, list, optional - Name of the layers to include in the plot. If ``None`` all the signal layers will be considered. - color_by_net : bool, optional - If ``True`` the plot will be colored by net. - If ``False`` the plot will be colored by layer. (default) - show_legend : bool, optional - If ``True`` the legend is shown in the plot. (default) - If ``False`` the legend is not shown. - save_plot : str, optional - If a path is specified the plot will be saved in this location. - If ``save_plot`` is provided, the ``show`` parameter is ignored. - outline : list, optional - List of points of the outline to plot. - size : tuple, int, optional - Image size in pixel (width, height). Default value is ``(2000, 1000)`` - plot_components_on_top : bool, optional - If ``True`` the components placed on top layer are plotted. - If ``False`` the components are not plotted. (default) - If nets and/or layers is specified, only the components belonging to the specified nets/layers are plotted. - plot_components_on_bottom : bool, optional - If ``True`` the components placed on bottom layer are plotted. - If ``False`` the components are not plotted. (default) - If nets and/or layers is specified, only the components belonging to the specified nets/layers are plotted. - show : bool, optional - Whether to show the plot or not. Default is `True`. - """ - from pyedb.generic.plot import plot_matplotlib - - object_lists = self.get_plot_data( - nets, - layers, - color_by_net, - outline, - plot_components_on_top, - plot_components_on_bottom, - ) - - if isinstance(size, int): # pragma: no cover - board_size_x, board_size_y = self._pedb.get_statistics().layout_size - fig_size_x = size - fig_size_y = board_size_y * fig_size_x / board_size_x - size = (fig_size_x, fig_size_y) - - plot_title = title - if plot_title is None: - plot_title = self._pedb.active_cell.GetName() - - return plot_matplotlib( - plot_data=object_lists, - size=size, - show_legend=show_legend, - xlabel="X (m)", - ylabel="Y (m)", - title=plot_title, - save_plot=save_plot, - axis_equal=True, - show=show, - ) def is_power_gound_net(self, netname_list): """Determine if one of the nets in a list is power or ground. diff --git a/src/pyedb/generic/filesystem.py b/src/pyedb/generic/filesystem.py index 5fff83ac71..767bda6f11 100644 --- a/src/pyedb/generic/filesystem.py +++ b/src/pyedb/generic/filesystem.py @@ -116,13 +116,10 @@ def copyfolder(self, src_folder, destfolder=None): ------- """ - from distutils.dir_util import copy_tree - if destfolder: - copy_tree(src_folder, destfolder) - else: + if not destfolder: destfolder = os.path.join(self.path, os.path.split(src_folder)[-1]) - copy_tree(src_folder, destfolder) + shutil.copytree(src_folder, destfolder, dirs_exist_ok=True) return destfolder def __enter__(self): From 5199f0c709cd081956f74e8b9d9a91caa973532a Mon Sep 17 00:00:00 2001 From: mcapodif Date: Mon, 18 Nov 2024 09:45:37 +0100 Subject: [PATCH 02/13] added new plot method --- src/pyedb/common/nets.py | 4 +++- .../dotnet/edb_core/edb_data/padstacks_data.py | 13 ++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/pyedb/common/nets.py b/src/pyedb/common/nets.py index 88500e7279..fc91a2fdc5 100644 --- a/src/pyedb/common/nets.py +++ b/src/pyedb/common/nets.py @@ -1,6 +1,6 @@ import math import time - +import os from pyedb.generic.constants import CSS4_COLORS def is_notebook(): @@ -144,6 +144,8 @@ def mirror_poly(poly): plot_line(poly.boundary, add_points=False, color=(0.7, 0, 0), linewidth=4) else: bbox = self._pedb.hfss.get_layout_bounding_box() + if not bbox: + return False, False x1 = bbox[0] x2 = bbox[2] y1 = bbox[1] diff --git a/src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py b/src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py index c9b20654bb..bdcf7f2886 100644 --- a/src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py +++ b/src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py @@ -1391,6 +1391,17 @@ def pin(self): @property def padstack_definition(self): + """Padstack definition Name. + + Returns + ------- + str + Name of the padstack definition. + """ + return self.definition.name + + @property + def definition(self): """Padstack definition. Returns @@ -1398,7 +1409,7 @@ def padstack_definition(self): str Name of the padstack definition. """ - self._pdef = self._edb_padstackinstance.GetPadstackDef().GetName() + self._pdef = EDBPadstack(self._edb_padstackinstance.GetPadstackDef(), self._pedb.padstacks) return self._pdef @property From 1c9eaa66e6258a911d4d148b76a1c87975319c8d Mon Sep 17 00:00:00 2001 From: mcapodif Date: Mon, 18 Nov 2024 09:51:27 +0100 Subject: [PATCH 03/13] added new plot method --- src/pyedb/dotnet/edb_core/hfss.py | 4 ++-- tests/legacy/system/test_edb_padstacks.py | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/pyedb/dotnet/edb_core/hfss.py b/src/pyedb/dotnet/edb_core/hfss.py index 219a40aa68..24131bd235 100644 --- a/src/pyedb/dotnet/edb_core/hfss.py +++ b/src/pyedb/dotnet/edb_core/hfss.py @@ -1168,8 +1168,8 @@ def get_layout_bounding_box(self, layout=None, digit_resolution=6): list [lower left corner X, lower left corner, upper right corner X, upper right corner Y]. """ - if layout == None: - return False + if layout is None: + layout = self._active_layout layout_obj_instances = layout.GetLayoutInstance().GetAllLayoutObjInstances() tuple_list = [] for lobj in layout_obj_instances.Items: diff --git a/tests/legacy/system/test_edb_padstacks.py b/tests/legacy/system/test_edb_padstacks.py index cc5728be4c..52c42b1a62 100644 --- a/tests/legacy/system/test_edb_padstacks.py +++ b/tests/legacy/system/test_edb_padstacks.py @@ -315,8 +315,9 @@ def test_padstaks_plot_on_matplotlib(self): assert os.path.exists(local_png1) local_png2 = os.path.join(self.local_scratch.path, "test2.png") + edb_plot.nets.plot( - nets="V3P3_S5", + nets="DDR4_DQS7_N", layers=None, save_plot=local_png2, plot_components_on_top=True, @@ -326,12 +327,12 @@ def test_padstaks_plot_on_matplotlib(self): local_png3 = os.path.join(self.local_scratch.path, "test3.png") edb_plot.nets.plot( - nets=["LVL_I2C_SCL", "V3P3_S5", "GATE_V5_USB"], - layers="TOP", + nets=["DDR4_DQ57", "DDR4_DQ56"], + layers="1_Top", color_by_net=True, save_plot=local_png3, - plot_components_on_top=True, - plot_components_on_bottom=True, + plot_components=True, + plot_vias=True, ) assert os.path.exists(local_png3) From 3cbfb98168d05427f378219536b24f892e547f7c Mon Sep 17 00:00:00 2001 From: mcapodif Date: Mon, 18 Nov 2024 09:53:52 +0100 Subject: [PATCH 04/13] Added requirements --- pyproject.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b81cf55b6e..86b333ee3b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,8 @@ tests = [ "pytest>=7.4.0,<8.4", "pytest-cov>=4.0.0,<6.1", "pytest-xdist>=3.5.0,<3.7", - "scikit-rf" + "scikit-rf", + "shapely" ] doc = [ "ansys-sphinx-theme>=0.10.0,<1.1", @@ -65,9 +66,12 @@ doc = [ "sphinx-copybutton>=0.5.0,<0.6", "sphinx-gallery>=0.14.0,<0.19", "sphinx_design>=0.4.0,<0.7", + "shapely", + ] full = [ "matplotlib>=3.5.0,<3.10", + "shapely", ] From ed73d0eba690a5682eaebaee5c4e32f55744d4f3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 08:55:44 +0000 Subject: [PATCH 05/13] MISC: Auto fixes from pre-commit.com hooks For more information, see https://pre-commit.ci --- src/pyedb/common/nets.py | 7 ++++--- src/pyedb/dotnet/edb_core/edb_data/nets_data.py | 1 - src/pyedb/dotnet/edb_core/nets.py | 2 -- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/pyedb/common/nets.py b/src/pyedb/common/nets.py index fc91a2fdc5..313d50ea89 100644 --- a/src/pyedb/common/nets.py +++ b/src/pyedb/common/nets.py @@ -1,8 +1,10 @@ import math -import time import os +import time + from pyedb.generic.constants import CSS4_COLORS + def is_notebook(): """Check if pyaedt is running in Jupyter or not. @@ -36,12 +38,11 @@ def is_ipython(): except NameError: return False # Probably standard Python interpreter + class CommonNets: def __init__(self, _pedb): self._pedb = _pedb - - def plot( self, nets=None, diff --git a/src/pyedb/dotnet/edb_core/edb_data/nets_data.py b/src/pyedb/dotnet/edb_core/edb_data/nets_data.py index f3be0997c1..9744824822 100644 --- a/src/pyedb/dotnet/edb_core/edb_data/nets_data.py +++ b/src/pyedb/dotnet/edb_core/edb_data/nets_data.py @@ -149,7 +149,6 @@ def plot( size=size, show=show, plot_vias=plot_vias, - ) def get_smallest_trace_width(self): diff --git a/src/pyedb/dotnet/edb_core/nets.py b/src/pyedb/dotnet/edb_core/nets.py index a89a04cf8c..853063c6f0 100644 --- a/src/pyedb/dotnet/edb_core/nets.py +++ b/src/pyedb/dotnet/edb_core/nets.py @@ -382,7 +382,6 @@ def _get_points_for_plot(self, my_net_points): # fmt: on return x, y - def classify_nets(self, power_nets=None, signal_nets=None): """Reassign power/ground or signal nets based on list of nets. @@ -414,7 +413,6 @@ def classify_nets(self, power_nets=None, signal_nets=None): self.nets[net].net_object.SetIsPowerGround(False) return True - def is_power_gound_net(self, netname_list): """Determine if one of the nets in a list is power or ground. From 12ad217395ffebe13879349e3b86c4c18d18c814 Mon Sep 17 00:00:00 2001 From: mcapodif Date: Mon, 18 Nov 2024 11:52:17 +0100 Subject: [PATCH 06/13] fixed docs --- examples/legacy_standalone/11_post_layout_parameterization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/legacy_standalone/11_post_layout_parameterization.py b/examples/legacy_standalone/11_post_layout_parameterization.py index eaf8d54fbd..7513dd0ef2 100644 --- a/examples/legacy_standalone/11_post_layout_parameterization.py +++ b/examples/legacy_standalone/11_post_layout_parameterization.py @@ -79,7 +79,7 @@ # Visualize the layout. -edb.nets.plot(layers=layers[0], size=2000) +edb.nets.plot(layers=layers[0]) # Save the AEDB file and close EDB. From 5810a8a7495d4ab984865c979e84c2afed861909 Mon Sep 17 00:00:00 2001 From: mcapodif Date: Mon, 18 Nov 2024 13:05:38 +0100 Subject: [PATCH 07/13] skip 0 tickness lines --- src/pyedb/common/nets.py | 44 ++++++++++++++++------- tests/legacy/system/test_edb_padstacks.py | 2 +- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/pyedb/common/nets.py b/src/pyedb/common/nets.py index 313d50ea89..6de4cc5ea9 100644 --- a/src/pyedb/common/nets.py +++ b/src/pyedb/common/nets.py @@ -57,6 +57,7 @@ def plot( show=True, annotate_component_names=True, plot_vias=False, + include_outline=True, **kwargs, ): """Plot a Net to Matplotlib 2D Chart. @@ -77,7 +78,7 @@ def plot( If a path is specified the plot will be saved in this location. If ``save_plot`` is provided, the ``show`` parameter is ignored. outline : list, optional - List of points of the outline to plot. + Add a customer outline from a list of points of the outline to plot. size : tuple, int, optional Image size in pixel (width, height). Default value is ``(6000, 3000)`` top_view : bool, optional @@ -94,6 +95,8 @@ def plot( Default is ``False``. show : bool, optional Whether to show the plot or not. Default is `True`. + include_outline : bool, optional + Whether to include the internal layout outline or not. Default is `True`. Returns ------- @@ -143,18 +146,29 @@ def mirror_poly(poly): if outline: poly = Polygon(outline) plot_line(poly.boundary, add_points=False, color=(0.7, 0, 0), linewidth=4) - else: - bbox = self._pedb.hfss.get_layout_bounding_box() - if not bbox: - return False, False - x1 = bbox[0] - x2 = bbox[2] - y1 = bbox[1] - y2 = bbox[3] - p = [(x1, y1), (x1, y2), (x2, y2), (x2, y1), (x1, y1)] - p = mirror_poly(p) - poly = LinearRing(p) - plot_line(poly, add_points=False, color=(0.7, 0, 0), linewidth=4) + elif include_outline: + prims = self._pedb.modeler.primitives_by_layer.get("Outline", []) + if prims: + for prim in prims: + if prim.is_void: + continue + xt, yt = prim.points() + p1 = [(i, j) for i, j in zip(xt[::-1], yt[::-1])] + p1 = mirror_poly(p1) + poly = LinearRing(p1) + plot_line(poly, add_points=False, color=(0.7, 0, 0), linewidth=4) + else: + bbox = self._pedb.hfss.get_layout_bounding_box() + if not bbox: + return False, False + x1 = bbox[0] + x2 = bbox[2] + y1 = bbox[1] + y2 = bbox[3] + p = [(x1, y1), (x1, y2), (x2, y2), (x2, y1), (x1, y1)] + p = mirror_poly(p) + poly = LinearRing(p) + plot_line(poly, add_points=False, color=(0.7, 0, 0), linewidth=4) layer_colors = {i: k.color for i, k in self._pedb.stackup.layers.items()} top_layer = list(self._pedb.stackup.signal_layers.keys())[0] bottom_layer = list(self._pedb.stackup.signal_layers.keys())[-1] @@ -284,12 +298,16 @@ def create_poly(prim, polys, lines): # poly = LineString(line).buffer(prim.width / 2) # else: xt, yt = prim.points() + if len(xt)<3: + return p1 = [(i, j) for i, j in zip(xt[::-1], yt[::-1])] p1 = mirror_poly(p1) holes = [] for void in prim.voids: xvt, yvt = void.points(arc_segments=3) + if len(xvt)<3: + continue h1 = mirror_poly([(i, j) for i, j in zip(xvt, yvt)]) holes.append(h1) poly = Polygon(p1, holes) diff --git a/tests/legacy/system/test_edb_padstacks.py b/tests/legacy/system/test_edb_padstacks.py index 52c42b1a62..1c0e23b946 100644 --- a/tests/legacy/system/test_edb_padstacks.py +++ b/tests/legacy/system/test_edb_padstacks.py @@ -324,7 +324,7 @@ def test_padstaks_plot_on_matplotlib(self): plot_components_on_bottom=True, ) assert os.path.exists(local_png2) - + edb_plot.modeler.create_polygon([[-10e-3, -10e-3], [110e-3, -10e-3], [110e-3, 70e-3], [-10e-3, 70e-3]],layer_name="Outline") local_png3 = os.path.join(self.local_scratch.path, "test3.png") edb_plot.nets.plot( nets=["DDR4_DQ57", "DDR4_DQ56"], From 75235e3b0dee8b1801b67b6bc397d7af6c2e57b0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 12:06:06 +0000 Subject: [PATCH 08/13] MISC: Auto fixes from pre-commit.com hooks For more information, see https://pre-commit.ci --- src/pyedb/common/nets.py | 4 ++-- tests/legacy/system/test_edb_padstacks.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pyedb/common/nets.py b/src/pyedb/common/nets.py index 6de4cc5ea9..65488114b2 100644 --- a/src/pyedb/common/nets.py +++ b/src/pyedb/common/nets.py @@ -298,7 +298,7 @@ def create_poly(prim, polys, lines): # poly = LineString(line).buffer(prim.width / 2) # else: xt, yt = prim.points() - if len(xt)<3: + if len(xt) < 3: return p1 = [(i, j) for i, j in zip(xt[::-1], yt[::-1])] p1 = mirror_poly(p1) @@ -306,7 +306,7 @@ def create_poly(prim, polys, lines): holes = [] for void in prim.voids: xvt, yvt = void.points(arc_segments=3) - if len(xvt)<3: + if len(xvt) < 3: continue h1 = mirror_poly([(i, j) for i, j in zip(xvt, yvt)]) holes.append(h1) diff --git a/tests/legacy/system/test_edb_padstacks.py b/tests/legacy/system/test_edb_padstacks.py index 1c0e23b946..67f9ffc443 100644 --- a/tests/legacy/system/test_edb_padstacks.py +++ b/tests/legacy/system/test_edb_padstacks.py @@ -324,7 +324,9 @@ def test_padstaks_plot_on_matplotlib(self): plot_components_on_bottom=True, ) assert os.path.exists(local_png2) - edb_plot.modeler.create_polygon([[-10e-3, -10e-3], [110e-3, -10e-3], [110e-3, 70e-3], [-10e-3, 70e-3]],layer_name="Outline") + edb_plot.modeler.create_polygon( + [[-10e-3, -10e-3], [110e-3, -10e-3], [110e-3, 70e-3], [-10e-3, 70e-3]], layer_name="Outline" + ) local_png3 = os.path.join(self.local_scratch.path, "test3.png") edb_plot.nets.plot( nets=["DDR4_DQ57", "DDR4_DQ56"], From 3408a1e46a15c0a51bd32083e84e9f24d8c9f684 Mon Sep 17 00:00:00 2001 From: mcapodif Date: Mon, 18 Nov 2024 13:51:42 +0100 Subject: [PATCH 09/13] skip 0 tickness lines --- src/pyedb/common/nets.py | 19 +++++++++++++++++-- src/pyedb/dotnet/edb_core/modeler.py | 5 ++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/pyedb/common/nets.py b/src/pyedb/common/nets.py index 6de4cc5ea9..932dccc87d 100644 --- a/src/pyedb/common/nets.py +++ b/src/pyedb/common/nets.py @@ -2,6 +2,8 @@ import os import time +import shapely + from pyedb.generic.constants import CSS4_COLORS @@ -58,6 +60,7 @@ def plot( annotate_component_names=True, plot_vias=False, include_outline=True, + plot_edges=True, **kwargs, ): """Plot a Net to Matplotlib 2D Chart. @@ -97,6 +100,8 @@ def plot( Whether to show the plot or not. Default is `True`. include_outline : bool, optional Whether to include the internal layout outline or not. Default is `True`. + plot_edges : bool, optional + Whether to plot polygon edges or not. Default is `True`. Returns ------- @@ -143,6 +148,7 @@ def mirror_poly(poly): layers = [layers] color_index = 0 label_colors = {} + edge_colors = {} if outline: poly = Polygon(outline) plot_line(poly.boundary, add_points=False, color=(0.7, 0, 0), linewidth=4) @@ -310,6 +316,12 @@ def create_poly(prim, polys, lines): continue h1 = mirror_poly([(i, j) for i, j in zip(xvt, yvt)]) holes.append(h1) + if len(holes)>1: + holes = shapely.union_all([Polygon(i) for i in holes]) + if isinstance(holes, MultiPolygon): + holes = [i.boundary for i in list(holes.geoms)] + else: + holes = [holes.boundary] poly = Polygon(p1, holes) if layer_name == "Outline": if label_colors[label] in lines: @@ -327,6 +339,7 @@ def create_poly(prim, polys, lines): continue label = "Net " + net label_colors[label] = list(CSS4_COLORS.keys())[color_index] + edge_colors[label] = [i * 0.5 for i in label_colors[label]] color_index += 1 if color_index >= len(CSS4_COLORS): color_index = 0 @@ -335,7 +348,7 @@ def create_poly(prim, polys, lines): if polys: ob = MultiPolygon(polys) plot_polygon( - ob, ax=ax, color=label_colors[label], add_points=False, alpha=0.7, label=label, edgecolor="none" + ob, ax=ax, color=label_colors[label], add_points=False, alpha=0.7, label=label, edgecolor="none" if not plot_edges else edge_colors[label] ) if lines: ob = MultiLineString(p) @@ -369,6 +382,8 @@ def create_poly(prim, polys, lines): if color_index >= len(CSS4_COLORS): color_index = 0 label_colors[label] = c + edge_colors[label] = [i*0.5 for i in c] + for prim in prims: create_poly(prim, polys, lines) if polys: @@ -380,7 +395,7 @@ def create_poly(prim, polys, lines): add_points=False, alpha=alpha, label=label, - edgecolor="none", + edgecolor="none" if not plot_edges else edge_colors[label], ) if lines: ob = MultiLineString(p) diff --git a/src/pyedb/dotnet/edb_core/modeler.py b/src/pyedb/dotnet/edb_core/modeler.py index 7644a723bc..f4ce332642 100644 --- a/src/pyedb/dotnet/edb_core/modeler.py +++ b/src/pyedb/dotnet/edb_core/modeler.py @@ -188,7 +188,10 @@ def primitives_by_layer(self): for lay in self._pedb.stackup.non_stackup_layers: _primitives_by_layer[lay] = [] for i in self._layout.primitives: - lay = i.layer.name + layer = i.layer + if not layer: + continue + lay = layer.name if lay in _primitives_by_layer: _primitives_by_layer[lay].append(i) return _primitives_by_layer From 3f2ed4de8159e9491e48313084e189992494265a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:46:44 +0000 Subject: [PATCH 10/13] MISC: Auto fixes from pre-commit.com hooks For more information, see https://pre-commit.ci --- src/pyedb/common/nets.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/pyedb/common/nets.py b/src/pyedb/common/nets.py index bcb102ea92..271436f414 100644 --- a/src/pyedb/common/nets.py +++ b/src/pyedb/common/nets.py @@ -316,7 +316,7 @@ def create_poly(prim, polys, lines): continue h1 = mirror_poly([(i, j) for i, j in zip(xvt, yvt)]) holes.append(h1) - if len(holes)>1: + if len(holes) > 1: holes = shapely.union_all([Polygon(i) for i in holes]) if isinstance(holes, MultiPolygon): holes = [i.boundary for i in list(holes.geoms)] @@ -348,7 +348,13 @@ def create_poly(prim, polys, lines): if polys: ob = MultiPolygon(polys) plot_polygon( - ob, ax=ax, color=label_colors[label], add_points=False, alpha=0.7, label=label, edgecolor="none" if not plot_edges else edge_colors[label] + ob, + ax=ax, + color=label_colors[label], + add_points=False, + alpha=0.7, + label=label, + edgecolor="none" if not plot_edges else edge_colors[label], ) if lines: ob = MultiLineString(p) @@ -382,7 +388,7 @@ def create_poly(prim, polys, lines): if color_index >= len(CSS4_COLORS): color_index = 0 label_colors[label] = c - edge_colors[label] = [i*0.5 for i in c] + edge_colors[label] = [i * 0.5 for i in c] for prim in prims: create_poly(prim, polys, lines) From 3a8107569a3867c3b2b87bda9332b679bd8384d2 Mon Sep 17 00:00:00 2001 From: mcapodif Date: Mon, 18 Nov 2024 15:34:27 +0100 Subject: [PATCH 11/13] skip 0 tickness lines --- src/pyedb/common/nets.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/pyedb/common/nets.py b/src/pyedb/common/nets.py index bcb102ea92..96e249a8a1 100644 --- a/src/pyedb/common/nets.py +++ b/src/pyedb/common/nets.py @@ -339,7 +339,10 @@ def create_poly(prim, polys, lines): continue label = "Net " + net label_colors[label] = list(CSS4_COLORS.keys())[color_index] - edge_colors[label] = [i * 0.5 for i in label_colors[label]] + try: + edge_colors[label] = [i * 0.5 for i in label_colors[label]] + except TypeError: + edge_colors[label] =label_colors[label] color_index += 1 if color_index >= len(CSS4_COLORS): color_index = 0 @@ -382,8 +385,10 @@ def create_poly(prim, polys, lines): if color_index >= len(CSS4_COLORS): color_index = 0 label_colors[label] = c - edge_colors[label] = [i*0.5 for i in c] - + try: + edge_colors[label] = [i*0.5 for i in c] + except TypeError: + edge_colors[label] =label_colors[label] for prim in prims: create_poly(prim, polys, lines) if polys: From 1ff788325f9a0feca204c8973a12a499f305ac8e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 14:37:32 +0000 Subject: [PATCH 12/13] MISC: Auto fixes from pre-commit.com hooks For more information, see https://pre-commit.ci --- src/pyedb/common/nets.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pyedb/common/nets.py b/src/pyedb/common/nets.py index d4b5bc23fb..96378e4938 100644 --- a/src/pyedb/common/nets.py +++ b/src/pyedb/common/nets.py @@ -342,7 +342,7 @@ def create_poly(prim, polys, lines): try: edge_colors[label] = [i * 0.5 for i in label_colors[label]] except TypeError: - edge_colors[label] =label_colors[label] + edge_colors[label] = label_colors[label] color_index += 1 if color_index >= len(CSS4_COLORS): color_index = 0 @@ -394,7 +394,7 @@ def create_poly(prim, polys, lines): try: edge_colors[label] = [i * 0.5 for i in c] except TypeError: - edge_colors[label] =label_colors[label] + edge_colors[label] = label_colors[label] for prim in prims: create_poly(prim, polys, lines) if polys: From 52dc671263b5f696c29c0b31fcd4c6083264a580 Mon Sep 17 00:00:00 2001 From: ring630 <@gmail.com> Date: Wed, 20 Nov 2024 15:37:20 +0100 Subject: [PATCH 13/13] fix pre-commit --- src/pyedb/dotnet/edb_core/nets.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/pyedb/dotnet/edb_core/nets.py b/src/pyedb/dotnet/edb_core/nets.py index 853063c6f0..12c7aae664 100644 --- a/src/pyedb/dotnet/edb_core/nets.py +++ b/src/pyedb/dotnet/edb_core/nets.py @@ -22,16 +22,12 @@ from __future__ import absolute_import # noreorder -import os -import time import warnings from pyedb.common.nets import CommonNets from pyedb.dotnet.edb_core.edb_data.nets_data import EDBNetsData -from pyedb.generic.constants import CSS4_COLORS from pyedb.generic.general_methods import generate_unique_name from pyedb.misc.utilities import compute_arc_points -from pyedb.modeler.geometry_operators import GeometryOperators class EdbNets(CommonNets):