kopia lustrzana https://github.com/corrscope/corrscope
				
				
				
			[wip] Create Axes using subplot(), flatten to 1D array in custom order
							rodzic
							
								
									0a11363f7b
								
							
						
					
					
						commit
						a14472b7ae
					
				| 
						 | 
					@ -6,6 +6,8 @@ from typing import NamedTuple, Optional, List, Tuple
 | 
				
			||||||
import click
 | 
					import click
 | 
				
			||||||
import matplotlib.pyplot as plt
 | 
					import matplotlib.pyplot as plt
 | 
				
			||||||
import numpy as np
 | 
					import numpy as np
 | 
				
			||||||
 | 
					from matplotlib.backends.backend_agg import FigureCanvasAgg
 | 
				
			||||||
 | 
					from matplotlib.figure import Figure
 | 
				
			||||||
from scipy.io import wavfile
 | 
					from scipy.io import wavfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ovgenpy.util import ceildiv
 | 
					from ovgenpy.util import ceildiv
 | 
				
			||||||
| 
						 | 
					@ -32,6 +34,8 @@ class RendererCfg(NamedTuple):
 | 
				
			||||||
    nrows: Optional[int] = None
 | 
					    nrows: Optional[int] = None
 | 
				
			||||||
    ncols: Optional[int] = None
 | 
					    ncols: Optional[int] = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # TODO backend: FigureCanvasBase = FigureCanvasAgg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Folder = click.Path(exists=True, file_okay=False)
 | 
					Folder = click.Path(exists=True, file_okay=False)
 | 
				
			||||||
File = click.Path(exists=True, dir_okay=False)
 | 
					File = click.Path(exists=True, dir_okay=False)
 | 
				
			||||||
| 
						 | 
					@ -154,59 +158,80 @@ class Trigger:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MatplotlibRenderer:
 | 
					class MatplotlibRenderer:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    If __init__ reads cfg, cfg cannot be hotswapped.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Reasons to hotswap cfg: RendererCfg:
 | 
				
			||||||
 | 
					    - GUI preview size
 | 
				
			||||||
 | 
					    - Changing layout
 | 
				
			||||||
 | 
					    - Changing #smp drawn (samples_visible)
 | 
				
			||||||
 | 
					    (see RendererCfg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Original OVGen does not support hotswapping.
 | 
				
			||||||
 | 
					        It disables changing options during rendering.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Reasons to hotswap trigger algorithms:
 | 
				
			||||||
 | 
					    - changing scan_nsamp (cannot be hotswapped, since correlation buffer is incompatible)
 | 
				
			||||||
 | 
					    So don't.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DPI = 96
 | 
					    DPI = 96
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, cfg: RendererCfg, waves: List[Wave]):
 | 
					    def __init__(self, cfg: RendererCfg, waves: List[Wave]):
 | 
				
			||||||
        self.cfg = cfg
 | 
					        self.cfg = cfg
 | 
				
			||||||
        self.waves = waves
 | 
					        self.waves = waves
 | 
				
			||||||
 | 
					        self.fig = Figure()
 | 
				
			||||||
 | 
					        FigureCanvasAgg(self.fig)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.dims: Tuple[int, int] = (0, 0)
 | 
					        # Setup layout
 | 
				
			||||||
        self.calc_layout()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.nrows = 0
 | 
				
			||||||
 | 
					        self.ncols = 0
 | 
				
			||||||
 | 
					        # Flat array of nrows*ncols elements, ordered by cfg.rows_first.
 | 
				
			||||||
 | 
					        self.axes: np.ndarray = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.set_layout()   # mutates self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_layout(self) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        If __init__ reads cfg, cfg cannot be hotswapped.
 | 
					        Inputs: self.cfg, self.waves, self.fig
 | 
				
			||||||
        
 | 
					        Outputs: self.nrows, self.ncols, self.axes
 | 
				
			||||||
        Reasons to hotswap cfg: RendererCfg:
 | 
					
 | 
				
			||||||
        - GUI preview size
 | 
					        Creates a flat array of Matplotlib axes, with the new layout.
 | 
				
			||||||
        - Changing layout
 | 
					 | 
				
			||||||
        - Changing #smp drawn (samples_visible)
 | 
					 | 
				
			||||||
        (see RendererCfg)
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            Original OVGen does not support hotswapping.
 | 
					 | 
				
			||||||
            It disables changing options during rendering.
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        Reasons to hotswap trigger algorithms:
 | 
					 | 
				
			||||||
        - changing scan_nsamp (cannot be hotswapped, since correlation buffer is incompatible)
 | 
					 | 
				
			||||||
        So don't.
 | 
					 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def calc_layout(self) -> None:
 | 
					        self.nrows, self.ncols = self.calc_layout()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # https://matplotlib.org/api/_as_gen/matplotlib.figure.Figure.html#matplotlib.figure.Figure.subplots
 | 
				
			||||||
 | 
					        axes2d = self.fig.subplots(self.nrows, self.ncols, squeeze=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # If column major:
 | 
				
			||||||
 | 
					        if not self.cfg.rows_first:
 | 
				
			||||||
 | 
					            axes2d = axes2d.T
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.axes = axes2d.flatten()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def calc_layout(self) -> Tuple[int, int]:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Inputs: self.cfg, self.waves
 | 
					        Inputs: self.cfg, self.waves
 | 
				
			||||||
        Outputs: self.dims
 | 
					        :return: (nmajor, nminor, nrows, ncols)
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        cfg = self.cfg
 | 
					        cfg = self.cfg
 | 
				
			||||||
 | 
					        nwaves = len(self.waves)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if cfg.rows_first:
 | 
					        if cfg.rows_first:
 | 
				
			||||||
            major = cfg.nrows
 | 
					            nrows = cfg.nrows
 | 
				
			||||||
            if major 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')
 | 
				
			||||||
 | 
					            ncols = ceildiv(nwaves, nrows)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            major = cfg.ncols
 | 
					            raise ValueError('rows_first=False not supported')
 | 
				
			||||||
            if major is None:
 | 
					            # nmajor = ncols = cfg.ncols
 | 
				
			||||||
                raise ValueError('invalid cfg: rows_first is False and ncols is None')
 | 
					            # if ncols is None:
 | 
				
			||||||
 | 
					            #     raise ValueError('invalid cfg: rows_first is False and ncols is None')
 | 
				
			||||||
 | 
					            # nminor = nrows = ceildiv(nwaves, ncols)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        minor = ceildiv(len(self.waves), major)
 | 
					        return nrows, ncols
 | 
				
			||||||
        self.dims = (major, minor)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _get_coords(self, idx: int):
 | 
					 | 
				
			||||||
        major, minor = np.unravel_index(idx, self.dims)
 | 
					 | 
				
			||||||
        if self.cfg.rows_first:
 | 
					 | 
				
			||||||
            row, col = major, minor
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            col, row = major, minor
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return Coords(row, col)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def render_frame(self, center_smps: List[int]) -> None:
 | 
					    def render_frame(self, center_smps: List[int]) -> None:
 | 
				
			||||||
        nwaves = len(self.waves)
 | 
					        nwaves = len(self.waves)
 | 
				
			||||||
| 
						 | 
					@ -230,7 +255,9 @@ class MatplotlibRenderer:
 | 
				
			||||||
        # plt.imshow(data, aspect='equal')
 | 
					        # plt.imshow(data, aspect='equal')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for idx, wave, center_smp in zip(count(), self.waves, center_smps):  # TODO
 | 
					        for idx, wave, center_smp in zip(count(), self.waves, center_smps):  # TODO
 | 
				
			||||||
            coords = self._get_coords(idx)
 | 
					            # coords = self._get_coords(idx)
 | 
				
			||||||
 | 
					            ax = self.axes[idx]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            print(wave)
 | 
					            print(wave)
 | 
				
			||||||
            print(center_smp)
 | 
					            print(center_smp)
 | 
				
			||||||
            print(coords)
 | 
					            print(coords)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Ładowanie…
	
		Reference in New Issue