Source code for finam_plot.grid_spec

"""Components for plotting grid specifications"""
import math

import finam as fm
import matplotlib.pyplot as plt

from .tools import create_figure


[docs] class GridSpecPlot(fm.Component): """Plots the geometry of grid specifications Uses :func:`matplotlib.pyplot.plot` and :func:`matplotlib.pyplot.scatter`. .. code-block:: text +--------------+ --> [custom] | | --> [custom] | GridSpecPlot | --> [......] | | +--------------+ Note: This component is push-based without an internal time step. Examples -------- .. testcode:: constructor import finam_plot as fmp plot = fmp.GridSpecPlot( inputs=["Grid1", "Grid2"], colors=["red", "#ff00ee"], ) .. testcode:: constructor :hide: plot.initialize() Parameters ---------- inputs : list List on input names. title : str, optional Title for plot and window. colors : list of str, optional List of colors for the inputs. Uses matplotlib default colors by default. pos : tuple(number, number), optional Figure position. ``int`` is interpreted as pixels, ``float`` is interpreted as fraction of screen size. size : tuple(number, number), optional Figure size. ``int`` is interpreted as pixels, ``float`` is interpreted as fraction of screen size. """ def __init__(self, inputs, title=None, colors=None, pos=None, size=None): super().__init__() self._figure = None self._names = inputs self._title = title self._colors = colors or [e["color"] for e in plt.rcParams["axes.prop_cycle"]] self._bounds = (pos, size) self._infos = {name: None for name in self._names} def _initialize(self): for name in self._names: self.inputs.add( io=fm.CallbackInput( name=name, callback=self._data_changed, time=None, grid=None, units=None, ) ) self.create_connector() def _connect(self, start_time): self.try_connect(start_time) for name, val in self._connector.in_infos.items(): if val is not None: self._infos[name] = val def _validate(self): self._update_plot() def _update(self): pass def _update_plot(self): self._figure, axes = create_figure(self._bounds) axes.set_aspect("equal") self._figure.canvas.manager.set_window_title(self._title or "FINAM") axes.set_title(self._title) for i, name in enumerate(self._infos): self._plot_grid(axes, name, self._colors[i % len(self._colors)]) self._figure.show() self._figure.tight_layout() self._figure.canvas.draw() self._figure.canvas.flush_events() def _finalize(self): pass def _plot_grid(self, axes, name, color): info = self._infos[name] data_points = info.grid.data_points points = info.grid.points cells = info.grid.cells if not isinstance(info.grid, fm.UnstructuredPoints): self._plot_cells(axes, points, cells, color) axes.scatter(*data_points.T[:2], marker="+", c=color) if not isinstance(info.grid, fm.data.StructuredGrid): return axes_inc = info.grid.axes_increase[:2] x_axis = info.grid.axes[0] y_axis = info.grid.axes[1] if not axes_inc[0]: x_axis = x_axis[::-1] if not axes_inc[1]: y_axis = y_axis[::-1] x = x_axis[0] y = y_axis[0] len_x = x_axis[-1] - x len_y = y_axis[-1] - y length_abs = 0.25 * min(abs(len_x), abs(len_y)) len_x = math.copysign(length_abs, len_x) len_y = math.copysign(length_abs, len_y) axes.arrow( x, y, len_x, 0, fc=color, head_width=0.05 * length_abs, length_includes_head=True, ) axes.arrow( x, y, 0, len_y, fc=color, head_width=0.05 * length_abs, length_includes_head=True, ) def _plot_cells(self, axes, points, cells, color): for nodes in cells: for i, node in enumerate(nodes): pt1 = points[node] pt2 = points[nodes[(i + 1) % len(nodes)]] axes.plot( [pt1[0], pt2[0]], [pt1[1], pt2[1]], c=color, lw=0.5, ) def _data_changed(self, _caller, _time): pass
# self.update()