Source code for glyph.observer

import logging

import matplotlib
import matplotlib.pyplot as plt
import numpy as np

logger = logging.getLogger(__name__)
EMPTY = np.array(1)


[docs]def get_limits(x, factor=1.1): """Calculates the plot range given an array x.""" avg = np.nanmean(x) range_ = np.nanmax(x) - np.nanmin(x) if range_ == 0: range_ = 0.5 return avg - range_ / 2 * factor, avg + range_ / 2 * factor
[docs]class ProgressObserver(object): # pragma: no cover def __init__(self): """Animates the progress of the evolutionary optimization. Note: Uses matplotlib's interactive mode. """ logger.debug("The ProgressObserver needs an interactive matplotlib backend.") logger.debug(f"Using {matplotlib.rcParams['backend']} as backend in matplotlib.") logger.debug("Try export MPLBACKEND='TkAgg'") plt.ion() self.fig = None self.axis = None self.lines = [] self.t_key = "gen" @staticmethod def _update_plt(ax, line, *data): x, y = data x = np.array(x) y = np.array(y) ax.relim() ax.autoscale_view() line.set_xdata(x) line.set_ydata(y) def _blank_canvas(self, chapters): self.fig, self.axes = plt.subplots(nrows=len(chapters) + 1) for c, ax in zip(chapters, self.axes): ax.set_xlabel(self.t_key) ax.set_ylabel(c) ax.set_title("Best " + c) (line,) = ax.plot(EMPTY, EMPTY) self.lines.append(line) (line,) = self.axes[-1].plot(EMPTY, EMPTY, "o-") self.axes[-1].set_xlabel(chapters[0]) self.axes[-1].set_ylabel(chapters[1]) self.axes[-1].set_title("Pareto Front") self.lines.append(line) plt.tight_layout()
[docs] def __call__(self, app): """ Note: To be used as a callback in :class:`glyph.application.Application`. Needs an interactive mpl backend. Args: app (glyph.application.Application) """ # see also https://github.com/matplotlib/matplotlib/issues/7886 if not matplotlib.is_interactive(): return chapters = sorted(app.logbook.chapters.keys()) if self.fig is None: self._blank_canvas(chapters) t = app.logbook.select(self.t_key) for c, ax, line in zip(chapters, self.axes, self.lines): self._update_plt(ax, line, t, app.logbook.chapters[c].select("min")) x, y = zip(*sorted([i.fitness.values for i in app.gp_runner.pareto_front])) self._update_plt(self.axes[-1], self.lines[-1], x, y) self.fig.canvas.draw()