kopia lustrzana https://github.com/corrscope/corrscope
Move layout rows/columns to class LayoutConfig
rodzic
2f4ebece70
commit
21d739cd4f
|
@ -5,7 +5,7 @@ from typing import Optional, List
|
|||
from ovgenpy import outputs
|
||||
from ovgenpy.channel import Channel, ChannelConfig
|
||||
from ovgenpy.config import register_config
|
||||
from ovgenpy.renderer import MatplotlibRenderer, RendererConfig
|
||||
from ovgenpy.renderer import MatplotlibRenderer, RendererConfig, LayoutConfig
|
||||
from ovgenpy.triggers import ITriggerConfig, CorrelationTriggerConfig
|
||||
from ovgenpy.utils import keyword_dataclasses as dc
|
||||
from ovgenpy.utils.keyword_dataclasses import field
|
||||
|
@ -30,6 +30,7 @@ class Config:
|
|||
trigger: ITriggerConfig # Maybe overriden per Wave
|
||||
|
||||
amplification: float
|
||||
layout: LayoutConfig
|
||||
render: RendererConfig
|
||||
|
||||
outputs: List[outputs.IOutputConfig]
|
||||
|
@ -60,10 +61,8 @@ def default_config(**kwargs):
|
|||
),
|
||||
|
||||
amplification=1,
|
||||
render=RendererConfig(
|
||||
1280, 720,
|
||||
ncols=1
|
||||
),
|
||||
layout=LayoutConfig(ncols=1),
|
||||
render=RendererConfig(1280, 720),
|
||||
|
||||
outputs=[
|
||||
# outputs.FFmpegOutputConfig(output),
|
||||
|
@ -100,7 +99,7 @@ class Ovgen:
|
|||
nframes = fps * self.waves[0].get_s()
|
||||
nframes = int(nframes) + 1
|
||||
|
||||
renderer = MatplotlibRenderer(self.cfg.render, self.nchan)
|
||||
renderer = MatplotlibRenderer(self.cfg.render, self.cfg.layout, self.nchan)
|
||||
|
||||
if RENDER_PROFILING:
|
||||
begin = time.perf_counter()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Optional, List, Tuple, TYPE_CHECKING, TypeVar, Callable
|
||||
from typing import Optional, List, TYPE_CHECKING, TypeVar, Callable
|
||||
|
||||
import matplotlib
|
||||
import numpy as np
|
||||
|
@ -22,24 +22,8 @@ class RendererConfig:
|
|||
width: int
|
||||
height: int
|
||||
|
||||
nrows: Optional[int] = None
|
||||
ncols: Optional[int] = None
|
||||
orientation: str = 'h'
|
||||
|
||||
create_window: bool = False
|
||||
|
||||
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:
|
||||
"""
|
||||
|
@ -64,10 +48,10 @@ class MatplotlibRenderer:
|
|||
|
||||
DPI = 96
|
||||
|
||||
def __init__(self, cfg: RendererConfig, nplots: int):
|
||||
def __init__(self, cfg: RendererConfig, lcfg: 'LayoutConfig', nplots: int):
|
||||
self.cfg = cfg
|
||||
self.nplots = nplots
|
||||
self.layout = RendererLayout(cfg, nplots)
|
||||
self.layout = RendererLayout(lcfg, nplots)
|
||||
|
||||
# Flat array of nrows*ncols elements, ordered by cfg.rows_first.
|
||||
self.fig: 'Figure' = None
|
||||
|
@ -162,13 +146,33 @@ class MatplotlibRenderer:
|
|||
return buffer_rgb
|
||||
|
||||
|
||||
@register_config
|
||||
class LayoutConfig:
|
||||
nrows: Optional[int] = None
|
||||
ncols: Optional[int] = None
|
||||
orientation: str = 'h'
|
||||
|
||||
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
|
||||
|
||||
|
||||
Region = TypeVar('Region')
|
||||
RegionFactory = Callable[[int, int], Region] # f(row, column) -> Region
|
||||
|
||||
|
||||
class RendererLayout:
|
||||
VALID_ORIENTATIONS = ['h', 'v']
|
||||
|
||||
def __init__(self, cfg: 'RendererConfig', nplots: int):
|
||||
def __init__(self, cfg: LayoutConfig, nplots: int):
|
||||
self.cfg = cfg
|
||||
self.nplots = nplots
|
||||
|
||||
|
|
|
@ -2,25 +2,28 @@ from unittest.mock import patch
|
|||
|
||||
import pytest
|
||||
|
||||
from ovgenpy.renderer import RendererConfig, MatplotlibRenderer
|
||||
from ovgenpy.renderer import RendererConfig, MatplotlibRenderer, LayoutConfig, \
|
||||
RendererLayout
|
||||
|
||||
|
||||
WIDTH = 640
|
||||
HEIGHT = 360
|
||||
|
||||
|
||||
def test_config():
|
||||
with pytest.raises(ValueError):
|
||||
RendererConfig(WIDTH, HEIGHT, nrows=1, ncols=1)
|
||||
LayoutConfig(nrows=1, ncols=1)
|
||||
|
||||
one_col = RendererConfig(WIDTH, HEIGHT, ncols=1)
|
||||
one_col = LayoutConfig(ncols=1)
|
||||
assert one_col
|
||||
|
||||
one_row = RendererConfig(WIDTH, HEIGHT, nrows=1)
|
||||
one_row = LayoutConfig(nrows=1)
|
||||
assert one_row
|
||||
|
||||
default = RendererConfig(WIDTH, HEIGHT)
|
||||
assert default.ncols == 1 # Should default to single-column layout
|
||||
default = LayoutConfig()
|
||||
assert default.ncols == 1 # Should default to single-column layout
|
||||
assert default.nrows is None
|
||||
assert default.orientation == 'h'
|
||||
|
||||
|
||||
def test_renderer():
|
||||
|
@ -33,15 +36,59 @@ def test_renderer():
|
|||
"""
|
||||
|
||||
# 2 columns
|
||||
cfg = RendererConfig(WIDTH, HEIGHT, ncols=2)
|
||||
cfg = RendererConfig(WIDTH, HEIGHT)
|
||||
lcfg = LayoutConfig(ncols=2)
|
||||
nplots = 15
|
||||
|
||||
r = MatplotlibRenderer(cfg, nplots)
|
||||
r = MatplotlibRenderer(cfg, lcfg, nplots)
|
||||
|
||||
# 2 columns, 8 rows
|
||||
assert r.layout.ncols == 2
|
||||
assert r.layout.nrows == 8
|
||||
|
||||
|
||||
@pytest.mark.parametrize('lcfg', [
|
||||
LayoutConfig(ncols=2),
|
||||
LayoutConfig(nrows=8),
|
||||
])
|
||||
def test_layout(lcfg):
|
||||
nplots = 15
|
||||
layout = RendererLayout(lcfg, nplots)
|
||||
|
||||
assert layout.ncols == 2
|
||||
assert layout.nrows == 8
|
||||
|
||||
# holy shit, passing tuples into a numpy array breaks things spectacularly, and it's
|
||||
# painfully difficult to stuff tuples into 1D array.
|
||||
# http://wesmckinney.com/blog/performance-quirk-making-a-1d-object-ndarray-of-tuples/
|
||||
regions = layout.arrange(lambda row, col: str((row, col)))
|
||||
assert len(regions) == nplots
|
||||
|
||||
assert regions[0] == '(0, 0)'
|
||||
assert regions[1] == '(0, 1)'
|
||||
assert regions[2] == '(1, 0)'
|
||||
m = nplots - 1
|
||||
assert regions[m] == str((m // 2, m % 2))
|
||||
|
||||
|
||||
@pytest.mark.parametrize('lcfg', [
|
||||
LayoutConfig(ncols=3, orientation='v'),
|
||||
LayoutConfig(nrows=3, orientation='v'),
|
||||
])
|
||||
def test_layout(lcfg):
|
||||
nplots = 7
|
||||
layout = RendererLayout(lcfg, nplots)
|
||||
|
||||
assert layout.ncols == 3
|
||||
assert layout.nrows == 3
|
||||
|
||||
regions = layout.arrange(lambda row, col: str((row, col)))
|
||||
assert len(regions) == nplots
|
||||
|
||||
assert regions[0] == '(0, 0)'
|
||||
assert regions[2] == '(2, 0)'
|
||||
assert regions[3] == '(0, 1)'
|
||||
assert regions[6] == '(0, 2)'
|
||||
|
||||
# TODO: test get_frame()
|
||||
# (integration test) ensure rendering to output works
|
||||
|
|
Ładowanie…
Reference in New Issue