diff --git a/corrscope/corrscope.py b/corrscope/corrscope.py index e4d5e3e..294d904 100644 --- a/corrscope/corrscope.py +++ b/corrscope/corrscope.py @@ -137,7 +137,7 @@ def template_config(**kwargs) -> Config: ), channels=[], default_label=DefaultLabel.FileName, - layout=LayoutConfig(orientation="v", stereo_orientation="v", ncols=1), + layout=LayoutConfig(orientation="v", stereo_orientation="v", ncols=0), render=RendererConfig( 1920, 1080, diff --git a/corrscope/layout.py b/corrscope/layout.py index c1e5a34..4ebb224 100644 --- a/corrscope/layout.py +++ b/corrscope/layout.py @@ -27,7 +27,9 @@ V = Orientation.v OVERLAY = StereoOrientation.overlay -class LayoutConfig(DumpableAttrs, always_dump="orientation stereo_orientation"): +class LayoutConfig( + DumpableAttrs, always_dump="orientation stereo_orientation nrows ncols" +): orientation: Orientation = attr.ib(default="h", converter=Orientation) nrows: Optional[int] = None ncols: Optional[int] = None @@ -45,9 +47,6 @@ class LayoutConfig(DumpableAttrs, always_dump="orientation stereo_orientation"): if self.nrows and self.ncols: raise CorrError("cannot manually assign both nrows and ncols") - if not self.nrows and not self.ncols: - self.ncols = 1 - class Edges(enum.Flag): NONE = 0 @@ -137,21 +136,20 @@ class RendererLayout: cfg = self.cfg if cfg.nrows: - if cfg.nrows is None: - raise ValueError("impossible cfg: nrows is None and true") # nrows=0 will never occur naturally, except for a broken config with # nrows=0, or in unit tests which set nwaves=0 (speed_hack). To prevent # tests from crashing, force nrows to 1 anyway. nrows = min(cfg.nrows, self.nwaves) or 1 ncols = ceildiv(self.nwaves, nrows) else: - if cfg.ncols is None: - raise ValueError( - "invalid LayoutConfig: nrows,ncols is None " - "(__attrs_post_init__ not called?)" - ) + # If both cfg.nrows and cfg.ncols are 0, default to auto layout. + # Set column count to 2 if we have 5 or more waves. + ncols = cfg.ncols + if not ncols: + ncols = 2 if self.nwaves >= 5 else 1 + # See nrows=0 comment above. - ncols = min(cfg.ncols, self.nwaves) or 1 + ncols = min(ncols, self.nwaves) or 1 nrows = ceildiv(self.nwaves, ncols) self.wave_nrow = nrows diff --git a/tests/test_layout.py b/tests/test_layout.py index 0a4b2e7..c0b0180 100644 --- a/tests/test_layout.py +++ b/tests/test_layout.py @@ -30,7 +30,8 @@ def test_layout_config(): assert one_row default = LayoutConfig() - assert default.ncols == 1 # Should default to single-column layout + # In a default LayoutConfig, default.ncols doesn't matter. See test_auto_layout() + # to verify we have the right behavior. assert default.nrows is None assert default.orientation == "h" @@ -117,6 +118,19 @@ def test_less_tracks_than_nrows_ncols(key, nplots): assert len(regions) == 1, (i, len(regions)) +@pytest.mark.parametrize("nplots", [1, 6]) +def test_auto_layout(nplots): + lcfg = LayoutConfig() + layout = RendererLayout(lcfg, [1] * nplots) + + if nplots >= 6: + assert layout.wave_ncol == 2 + assert layout.wave_nrow == ceildiv(nplots, 2) + else: + assert layout.wave_ncol == 1 + assert layout.wave_nrow == nplots + + @given( wave_nchans=hs.lists(hs.integers(1, 10), min_size=1, max_size=100), orientation=hs.sampled_from(Orientation),