Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added method to plot Edb in Linux with Client Server mode #791

Merged
merged 4 commits into from
Jan 31, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyaedt/application/Analysis2D.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def plot(

Returns
-------
:class:`pyaedt.modules.AdvancedPostProcessing.ModelPlotter`
:class:`pyaedt.generic.plot.ModelPlotter`
Model Object.
"""
if is_ironpython:
Expand Down
2 changes: 1 addition & 1 deletion pyaedt/application/Analysis3D.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def plot(

Returns
-------
:class:`pyaedt.modules.AdvancedPostProcessing.ModelPlotter`
:class:`pyaedt.generic.plot.ModelPlotter`
Model Object.
"""
if is_ironpython:
Expand Down
2 changes: 1 addition & 1 deletion pyaedt/application/AnalysisIcepak.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def plot(

Returns
-------
:class:`pyaedt.modules.AdvancedPostProcessing.ModelPlotter`
:class:`pyaedt.generic.plot.ModelPlotter`
Model Object.
"""
if is_ironpython:
Expand Down
2 changes: 1 addition & 1 deletion pyaedt/edb_core/EDB_Data.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def _eval_arc_points(p1, p2, h, n=6, tol=1e-12):
yr = []
for i in range(n):
i += 1
dth = (i/(n+1)) * th
dth = (float(i)/(n+1)) * th
xi = xc + r * math.cos(alpha-dth)
yi = yc + r * math.sin(alpha-dth)
xr.append(xi)
Expand Down
132 changes: 68 additions & 64 deletions pyaedt/edb_core/nets.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from __future__ import absolute_import
import warnings
import time
import math

Expand All @@ -8,18 +7,7 @@
from pyaedt.modeler.GeometryOperators import GeometryOperators
from pyaedt.generic.constants import CSS4_COLORS
from pyaedt.edb_core.EDB_Data import EDBNetsData

if not is_ironpython:
try:
from matplotlib import pyplot as plt
from matplotlib.path import Path
from matplotlib.patches import PathPatch
except ImportError:
mess = "The Matplotlib module is required to run some functionalities.\n"
mess += "Install with \npip install matplotlib"
warnings.warn(mess)
except:
pass
from pyaedt.generic.plot import plot_matplotlib


class EdbNets(object):
Expand Down Expand Up @@ -221,10 +209,14 @@ def _get_points_for_plot(self, my_net_points):
return x, y

@aedt_exception_handler
def plot(
self, nets, layers=None, color_by_net=False, show_legend=True, save_plot=None, outline=None, size=(2000, 1000)
def get_plot_data(
self,
nets,
layers=None,
color_by_net=False,
outline=None,
):
"""Plot a Net to Matplotlib 2D Chart.
"""Return List of points for Matplotlib 2D Chart.

Parameters
----------
Expand All @@ -235,35 +227,21 @@ def plot(
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 `None` the plot will be shown.
If a file path is specified the plot will be saved to such file.
outline : list, optional
List of points of the outline to plot.
size : tuple, optional
Image size in pixel (width, height).
"""
start_time = time.time()
if is_ironpython:
self._logger.warning("Plot functionalities are enabled only in CPython.")
return False
color_index = 0
if not layers:
layers = list(self._pedb.core_stackup.signal_layers.keys())
if not nets:
nets = list(self.nets.keys())
objects_lists = []
label_colors = {}
color_index = 0
dpi = 100.0
figsize = (size[0] / dpi, size[1] / dpi)
fig, ax = plt.subplots(figsize=figsize)
if outline:
x1 = [i[0] for i in outline]
y1 = [i[1] for i in outline]
plt.fill(x1, y1, c="b", label="Outline", alpha=0.3)

objects_lists.append([x1, y1, "b", "Outline", 0.3, "fill"])
if isinstance(nets, str):
nets = [nets]

Expand All @@ -279,26 +257,27 @@ def plot(
if label not in label_colors:
color = path.layer.GetColor()
try:
c = (color.Item1 / 255, color.Item2 / 255, color.Item3 / 255)
c = (float(color.Item1 / 255), float(color.Item2 / 255), float(color.Item3 / 255))
label_colors[label] = c
except:
label_colors[label] = list(CSS4_COLORS.keys())[color_index]
color_index += 1
if color_index >= len(CSS4_COLORS):
color_index = 0
plt.fill(x, y, c=label_colors[label], label=label, alpha=0.4)
objects_lists.append([x, y, label_colors[label], label, 0.4, "fill"])
else:
plt.fill(x, y, c=label_colors[label], alpha=0.4)
objects_lists.append([x, y, label_colors[label], None, 0.4, "fill"])

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
plt.fill(x, y, c=label_colors[label], label=label, alpha=0.4)
objects_lists.append([x, y, label_colors[label], label, 0.4, "fill"])
else:
plt.fill(x, y, c=label_colors[label], alpha=0.4)
objects_lists.append([x, y, label_colors[label], None, 0.4, "fill"])

for poly in self._pedb.core_primitives.polygons:
if poly.is_void:
Expand All @@ -311,43 +290,42 @@ def plot(
continue
x, y = GeometryOperators.orient_polygon(xt, yt, clockwise=True)
vertices = [(i, j) for i, j in zip(x, y)]
codes = [Path.LINETO for _ in vertices]
codes[0] = Path.MOVETO
codes = [2 for _ in vertices]
codes[0] = 1
vertices.append((0, 0))
codes.append(Path.CLOSEPOLY)
codes.append(79)

for void in poly.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 = [Path.LINETO for _ in tmpV]
tmpC[0] = Path.MOVETO
tmpC = [2 for _ in tmpV]
tmpC[0] = 1
codes.extend(tmpC)
vertices.append((0, 0))
codes.append(Path.CLOSEPOLY)

# create Path object from vertices and codes
path = Path(vertices, codes)
codes.append(79)

if not color_by_net:
label = "Layer " + layer_name
if label not in label_colors:
color = poly.GetLayer().GetColor()
try:
c = (color.Item1 / 255, color.Item2 / 255, color.Item3 / 255)
c = (float(color.Item1 / 255), float(color.Item2 / 255), float(color.Item3 / 255))
label_colors[label] = c
except:
label_colors[label] = list(CSS4_COLORS.keys())[color_index]
color_index += 1
if color_index >= len(CSS4_COLORS):
color_index = 0
# create patch from path
patch = PathPatch(path, color=label_colors[label], alpha=0.4, label=label)
objects_lists.append([vertices, codes, label_colors[label], label, 0.4, "path"])

else:
# create patch from path
patch = PathPatch(path, color=label_colors[label], alpha=0.4)
objects_lists.append([vertices, codes, label_colors[label], "", 0.4, "path"])

else:
label = "Net " + net_name
if label not in label_colors:
Expand All @@ -356,24 +334,50 @@ def plot(
if color_index >= len(CSS4_COLORS):
color_index = 0
# create patch from path
patch = PathPatch(path, color=label_colors[label], alpha=0.4, label=label)
objects_lists.append([vertices, codes, label_colors[label], label, 0.4, "path"])
else:
# create patch from path
patch = PathPatch(path, color=label_colors[label], alpha=0.4)
objects_lists.append([vertices, codes, label_colors[label], "", 0.4, "path"])
end_time = time.time() - start_time
self._logger.info("Nets Point Generation time %s seconds", round(end_time, 3))
return objects_lists

# plot the patch
ax.add_patch(patch)
@aedt_exception_handler
def plot(
self, nets, layers=None, color_by_net=False, show_legend=True, save_plot=None, outline=None, size=(2000, 1000)
):
"""Plot a Net to Matplotlib 2D Chart.

ax.set(xlabel="X (m)", ylabel="Y (m)", title=self._pedb.active_cell.GetName())
if show_legend:
ax.legend()
ax.axis("equal")
end_time = time.time() - start_time
self._logger.info("Plot Generation time %s seconds", round(end_time, 3))
if save_plot:
plt.savefig(save_plot)
else:
plt.show()
Parameters
----------
nets : str, list
Name of the net or list of nets to plot. If `None` all nets will be plotted.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maxcapodi78 Maybe the default value should be a string: "all" instead of None to indicate that by default all layers or nets are plotted.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea but maybe we should think to a biggest refactoring since this approach (with None) is widely used in pyaedt and users expect the same behaviour.

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 `None` the plot will be shown.
If a file path is specified the plot will be saved to such file.
outline : list, optional
List of points of the outline to plot.
size : tuple, optional
Image size in pixel (width, height).
maxcapodi78 marked this conversation as resolved.
Show resolved Hide resolved
"""
if is_ironpython:
self._logger.warning("Plot functionalities are enabled only in CPython.")
return False
object_lists = self.get_plot_data(
nets,
layers,
color_by_net,
outline,
)
plot_matplotlib(object_lists, size, show_legend, "X (m)", "Y (m)", self._pedb.active_cell.GetName(), save_plot)

@aedt_exception_handler
def is_power_gound_net(self, netname_list):
Expand Down
16 changes: 13 additions & 3 deletions pyaedt/generic/general_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,24 @@ def convert_remote_object(arg):
"""
if _check_types(arg) == "list":
if arg.__len__() > 0:
if isinstance(arg[0], (int, float, str, dict)):
return list(eval(str(arg)))
if (
isinstance(arg[0], (int, float, str))
or _check_types(arg[0]) == "list"
or _check_types(arg[0]) == "dict"
):
a = list(eval(str(arg)))
for i, el in enumerate(a):
a[i] = convert_remote_object(el)
return a
else:
return [arg[i] for i in range(arg.__len__())]
else:
return []
elif _check_types(arg) == "dict":
return dict(eval(str(arg)))
a = dict(eval(str(arg)))
for k, v in a.items():
a[k] = convert_remote_object(v)
return a
return arg


Expand Down
Loading