line_plot.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. from typing import List
  2. from .plot import Plot
  3. class LinePlot(Plot):
  4. def __init__(self,
  5. *,
  6. n: int = 1,
  7. limit: int = 100,
  8. update_every=1,
  9. close: bool = True,
  10. **kwargs,
  11. ):
  12. """Line Plot
  13. Create a line plot. The `push` method provides live updating when utilized in combination with `ui.timer`.
  14. :param n: number of lines
  15. :param limit: maximum number of datapoints per line (new points will displace the oldest)
  16. :param update_every: update plot only after pushing new data multiple times to save CPU and bandwidth
  17. :param close: whether the figure should be closed after exiting the context; set to `False` if you want to update it later, default is `True`
  18. :param kwargs: arguments like `figsize` which should be passed to `pyplot.figure <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.figure.html>`_
  19. """
  20. super().__init__(close=close, **kwargs)
  21. self.x = []
  22. self.Y = [[] for _ in range(n)]
  23. self.lines = [self.fig.gca().plot([], [])[0] for _ in range(n)]
  24. self.slice = slice(0 if limit is None else -limit, None)
  25. self.update_every = update_every
  26. self.push_counter = 0
  27. def with_legend(self, titles: List[str], **kwargs):
  28. self.fig.gca().legend(titles, **kwargs)
  29. self.view.set_figure(self.fig)
  30. return self
  31. def push(self, x: List[float], Y: List[List[float]]):
  32. self.push_counter += 1
  33. self.x = [*self.x, *x][self.slice]
  34. for i in range(len(self.lines)):
  35. self.Y[i] = [*self.Y[i], *Y[i]][self.slice]
  36. if self.push_counter % self.update_every != 0:
  37. return
  38. for i in range(len(self.lines)):
  39. self.lines[i].set_xdata(self.x)
  40. self.lines[i].set_ydata(self.Y[i])
  41. flat_y = [y_i for y in self.Y for y_i in y]
  42. min_x = min(self.x)
  43. max_x = max(self.x)
  44. min_y = min(flat_y)
  45. max_y = max(flat_y)
  46. pad_x = 0.01 * (max_x - min_x)
  47. pad_y = 0.01 * (max_y - min_y)
  48. self.fig.gca().set_xlim(min_x - pad_x, max_x + pad_x)
  49. self.fig.gca().set_ylim(min_y - pad_y, max_y + pad_y)
  50. self.view.set_figure(self.fig)