Source code for pyleecan.GUI.Tools.WMeshSolution.WMeshSolution

# -*- coding: utf-8 -*-
import matplotlib.cm as cm

from numpy import sqrt

from PySide2.QtWidgets import QAbstractSpinBox, QSpinBox, QWidget, QLabel
from PySide2.QtWidgets import QVBoxLayout, QHBoxLayout

from ..MPLWidget import MPLWidget
from ..CheckableComboBox import CheckableComboBox
from ..FloatEdit import FloatEdit


ALL_GROUPS = "all"


[docs]class WMeshSolution(QWidget): """Widget to view the data on a MeshSolution object.""" def __init__(self, obj, *args, **kwargs): QWidget.__init__(self, *args, **kwargs) # the object and some data cache self.obj = obj self._meshsolution = None self._mesh = None self._label = None self._axes = None self._field = None self._vmin = 0 self._vmax = 1 # the plot widget self.plotWidget = MPLWidget(is_toolbar=True, is_horizontal=True) self.setupUi() # signals self.groupSelection.selectionChanged.connect(self.onSelectionChanged) self.labelSelection.selectionChanged.connect(self.onSelectionChanged) self.indexSelection.valueChanged.connect(self.onIndexChanged) self.colorLevelEdit.editingFinished.connect(self.plot) self.minValueEdit.editingFinished.connect(self.onRangeChanged) self.maxValueEdit.editingFinished.connect(self.onRangeChanged) # finalize self.onSelectionChanged() # trigger initial plot
[docs] def setupUi(self): self.mainLayout = QVBoxLayout() self.subLayout = QHBoxLayout() groups = [ALL_GROUPS] groups.extend(list(self.obj.group.keys())) self.groupSelection = CheckableComboBox(label="Groups", allowNoSelection=False) self.groupSelection.addItems(groups) self.labelSelection = CheckableComboBox( label="Solution", allowNoSelection=False, singleSelection=True ) self.labelSelection.addItems([sol.label for sol in self.obj.solution]) self.indexLabel = QLabel() self.indexSelection = QSpinBox() self.indexSelection.setMinimum(0) self.indexSelection.setMaximum(0) self.indexSelection.setValue(0) self.colorLevelEdit = QSpinBox() self.colorLevelEdit.setButtonSymbols(QAbstractSpinBox.NoButtons) self.colorLevelEdit.setMinimum(256) self.colorLevelEdit.setMinimum(2) self.colorLevelEdit.setValue(11) self.minValueEdit = FloatEdit() self.maxValueEdit = FloatEdit() self.mainLayout.addWidget(self.groupSelection) self.mainLayout.addWidget(self.labelSelection) self.mainLayout.addLayout(self.subLayout) self.mainLayout.addWidget(self.plotWidget) self.subLayout.addWidget(self.indexLabel) self.subLayout.addWidget(self.indexSelection) self.subLayout.addWidget(QLabel("Min.")) self.subLayout.addWidget(self.minValueEdit) self.subLayout.addWidget(QLabel("Max.")) self.subLayout.addWidget(self.maxValueEdit) self.subLayout.addWidget(QLabel("Color Levels")) self.subLayout.addWidget(self.colorLevelEdit) self.setLayout(self.mainLayout) self.setMinimumWidth(700)
[docs] def onIndexChanged(self): self.plot()
[docs] def onRangeChanged(self): vmin, vmax = self.minValueEdit.value(), self.maxValueEdit.value() self._vmin = vmin or self._vmin self._vmax = vmax or self._vmax self.plot()
[docs] def onSelectionChanged(self): labels = self.labelSelection.currentData() groups = self.groupSelection.currentData() if labels and groups: is_update_range = False if self._label != labels[0]: self._label = labels[0] is_update_range = True if ALL_GROUPS in groups: self._meshsolution = self.obj else: self._meshsolution = self.obj.get_group(groups) self._mesh = self._meshsolution.get_mesh().copy() self._mesh.renum() # TODO a bug? mesh should already be renumbered axes, siz = self._meshsolution.get_solution(self._label).get_axes_list() if axes[0] not in ["component", "indice"]: self.indexSelection.setMaximum(siz[0] - 1) self.indexLabel.setText(f"'{axes[0]}' axis index") self._axes = axes self._field = self._meshsolution.get_field( *axes, label=self._label, is_squeeze=False ) if "component" in axes: ii = axes.index("component") self._field = sqrt((self._field ** 2).sum(axis=ii)) if is_update_range: self.resetRange() self.plot() else: self.clear()
[docs] def plot(self, levels=11): """Plot Filled Contour Clipped by Polygon Parameters ---------- levels : int numbers of colors in the plot Outputs ------- none : """ # get figure fig = self.plotWidget.get_figure() fig.clear() ax = fig.add_subplot(111) # get the data to plot field = self._field if self._axes[0] not in ["component", "indice"]: index = self.indexSelection.value() field = field[index] xy = self._mesh.get_node() tri = self._mesh.get_cell()[0]["triangle"] # plot x, y = xy[:, 0], xy[:, 1] kwargs = { "cmap": cm.get_cmap("jet", lut=self.colorLevelEdit.value()), "vmin": self._vmin, "vmax": self._vmax, # "shading": "gouraud" # doesn't work with facecolors } cont1 = ax.tripcolor(x, y, tri, facecolors=field, **kwargs) # generate a colorbar cbar = fig.colorbar(cont1, ax=ax) # cbar.set_ticks(cont1.levels) # cbar.set_ticklabels(np_round(cont1.levels, 2)) if self._label not in ["", None]: cbar.ax.set_title(self._label) # plt.grid(c='k', ls='-', alpha=0.3) # cbar.set_label(axislabel[2]) # ax.set_xlim(x_max, x_min) # ax.set_ylim(y_max, y_min) ax.set_aspect(1) self.plotWidget.draw()
[docs] def clear(self): fig = self.plotWidget.get_figure() fig.clear() self.plotWidget.draw()
[docs] def resetRange(self): self._vmin, self._vmax = self._field.min(), self._field.max() self._vmin = 0 if self._vmin > 0 else self._vmin self.minValueEdit.setValue(self._vmin) self.maxValueEdit.setValue(self._vmax)