kopia lustrzana https://github.com/corrscope/corrscope
RendererConfig calculates orientation based on nrows or ncols.
- Ensure either nrows or ncols is set. - If neither, set ncols=1 (single column). - Remove rows_first flag. Add test_renderer.pypull/357/head
rodzic
8b71df0bbb
commit
2ad624be03
|
@ -50,7 +50,6 @@ def main(wave_dir: str, master_wave: Optional[str], fps: int):
|
||||||
),
|
),
|
||||||
render=RendererConfig( # todo
|
render=RendererConfig( # todo
|
||||||
1280, 720,
|
1280, 720,
|
||||||
rows_first=False,
|
|
||||||
ncols=1
|
ncols=1
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from typing import NamedTuple, Optional, List, Tuple
|
from typing import NamedTuple, Optional, List, Tuple
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from dataclasses import dataclass
|
||||||
from matplotlib import pyplot as plt
|
from matplotlib import pyplot as plt
|
||||||
from matplotlib.axes import Axes
|
from matplotlib.axes import Axes
|
||||||
from matplotlib.figure import Figure
|
from matplotlib.figure import Figure
|
||||||
|
@ -9,21 +10,29 @@ from matplotlib.lines import Line2D
|
||||||
from ovgenpy.util import ceildiv
|
from ovgenpy.util import ceildiv
|
||||||
|
|
||||||
|
|
||||||
class RendererConfig(NamedTuple):
|
@dataclass
|
||||||
|
class RendererConfig:
|
||||||
width: int
|
width: int
|
||||||
height: int
|
height: int
|
||||||
|
|
||||||
rows_first: bool
|
nrows: Optional[int] = None
|
||||||
|
|
||||||
nrows: Optional[int] = None # TODO set to 1
|
|
||||||
ncols: Optional[int] = None
|
ncols: Optional[int] = None
|
||||||
|
|
||||||
# TODO backend: FigureCanvasBase = FigureCanvasAgg
|
def __post_init__(self):
|
||||||
|
if not self.nrows:
|
||||||
|
self.nrows = None
|
||||||
|
if not self.ncols:
|
||||||
|
self.ncols = None
|
||||||
|
|
||||||
|
if self.nrows and self.ncols:
|
||||||
|
raise ValueError('cannot manually assign both nrows and ncols')
|
||||||
|
|
||||||
|
if not self.nrows and not self.ncols:
|
||||||
|
self.ncols = 1
|
||||||
|
|
||||||
|
|
||||||
class MatplotlibRenderer:
|
class MatplotlibRenderer:
|
||||||
"""
|
"""
|
||||||
TODO disable antialiasing
|
|
||||||
If __init__ reads cfg, cfg cannot be hotswapped.
|
If __init__ reads cfg, cfg cannot be hotswapped.
|
||||||
|
|
||||||
Reasons to hotswap cfg: RendererCfg:
|
Reasons to hotswap cfg: RendererCfg:
|
||||||
|
@ -48,6 +57,8 @@ class MatplotlibRenderer:
|
||||||
self.fig: Figure = None
|
self.fig: Figure = None
|
||||||
|
|
||||||
# Setup layout
|
# Setup layout
|
||||||
|
# "ncols=1" is good for vertical layouts.
|
||||||
|
# But "nrows=X" is good for left-to-right grids.
|
||||||
|
|
||||||
self.nrows = 0
|
self.nrows = 0
|
||||||
self.ncols = 0
|
self.ncols = 0
|
||||||
|
@ -60,13 +71,14 @@ class MatplotlibRenderer:
|
||||||
|
|
||||||
def set_layout(self) -> None:
|
def set_layout(self) -> None:
|
||||||
"""
|
"""
|
||||||
Inputs: self.cfg, self.waves, self.fig
|
|
||||||
Outputs: self.nrows, self.ncols, self.axes
|
|
||||||
|
|
||||||
Creates a flat array of Matplotlib Axes, with the new layout.
|
Creates a flat array of Matplotlib Axes, with the new layout.
|
||||||
|
Opens a window showing the Figure (and Axes).
|
||||||
|
|
||||||
|
Inputs: self.cfg, self.fig
|
||||||
|
Outputs: self.nrows, self.ncols, self.axes
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.nrows, self.ncols = self.calc_layout()
|
self.nrows, self.ncols = self._calc_layout()
|
||||||
|
|
||||||
# Create Axes
|
# Create Axes
|
||||||
# https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplots.html
|
# https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplots.html
|
||||||
|
@ -86,7 +98,7 @@ class MatplotlibRenderer:
|
||||||
ax.set_axis_off()
|
ax.set_axis_off()
|
||||||
|
|
||||||
# if column major:
|
# if column major:
|
||||||
if not self.cfg.rows_first:
|
if self.cfg.ncols:
|
||||||
axes2d = axes2d.T
|
axes2d = axes2d.T
|
||||||
|
|
||||||
self.axes: List[Axes] = axes2d.flatten().tolist()[:self.nplots]
|
self.axes: List[Axes] = axes2d.flatten().tolist()[:self.nplots]
|
||||||
|
@ -99,14 +111,14 @@ class MatplotlibRenderer:
|
||||||
)
|
)
|
||||||
plt.show(block=False)
|
plt.show(block=False)
|
||||||
|
|
||||||
def calc_layout(self) -> Tuple[int, int]:
|
def _calc_layout(self) -> Tuple[int, int]:
|
||||||
"""
|
"""
|
||||||
Inputs: self.cfg, self.waves
|
Inputs: self.cfg, self.waves
|
||||||
:return: (nrows, ncols)
|
:return: (nrows, ncols)
|
||||||
"""
|
"""
|
||||||
cfg = self.cfg
|
cfg = self.cfg
|
||||||
|
|
||||||
if cfg.rows_first:
|
if cfg.nrows:
|
||||||
nrows = cfg.nrows
|
nrows = cfg.nrows
|
||||||
if nrows is None:
|
if nrows is None:
|
||||||
raise ValueError('invalid cfg: rows_first is True and nrows is None')
|
raise ValueError('invalid cfg: rows_first is True and nrows is None')
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
|
||||||
|
from ovgenpy.renderer import RendererConfig, MatplotlibRenderer
|
||||||
|
|
||||||
|
|
||||||
|
WIDTH = 640
|
||||||
|
HEIGHT = 360
|
||||||
|
|
||||||
|
def test_config():
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
RendererConfig(WIDTH, HEIGHT, nrows=1, ncols=1)
|
||||||
|
|
||||||
|
one_col = RendererConfig(WIDTH, HEIGHT, ncols=1)
|
||||||
|
assert one_col
|
||||||
|
|
||||||
|
one_row = RendererConfig(WIDTH, HEIGHT, nrows=1)
|
||||||
|
assert one_row
|
||||||
|
|
||||||
|
default = RendererConfig(WIDTH, HEIGHT)
|
||||||
|
assert default.ncols == 1 # Should default to single-column layout
|
||||||
|
assert default.nrows is None
|
||||||
|
|
||||||
|
|
||||||
|
@patch("ovgenpy.renderer.plt.show")
|
||||||
|
def test_renderer(mock_show):
|
||||||
|
"""
|
||||||
|
TODO check image output using:
|
||||||
|
https://matplotlib.org/devel/testing.html#writing-an-image-comparison-test
|
||||||
|
|
||||||
|
https://stackoverflow.com/a/27950953
|
||||||
|
"[I]mage comparison tests end up bring more trouble than they are worth"
|
||||||
|
"""
|
||||||
|
# monkeypatch.setattr(plt, 'show', lambda *args, **kwargs: None)
|
||||||
|
|
||||||
|
# 2 columns
|
||||||
|
cfg = RendererConfig(WIDTH, HEIGHT, ncols=2)
|
||||||
|
nplots = 16
|
||||||
|
|
||||||
|
r = MatplotlibRenderer(cfg, nplots)
|
||||||
|
|
||||||
|
# 2 columns, 8 rows
|
||||||
|
assert r.ncols == 2
|
||||||
|
assert r.nrows == 8
|
Ładowanie…
Reference in New Issue