kopia lustrzana https://github.com/corrscope/corrscope
Rename ovgenpy to corrscope
rodzic
9aceabb2b7
commit
5c47c293cb
|
@ -0,0 +1 @@
|
|||
corrscope
|
|
@ -9,7 +9,7 @@
|
|||
<excludeFolder url="file://$MODULE_DIR$/ovgenpy.build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ovgenpy.egg-info" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.6 (ovgenpy)" jdkType="Python SDK" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.7 (corrscope-py3.7)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="PackageRequirementsSettings">
|
|
@ -3,5 +3,5 @@
|
|||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6 (ovgenpy)" project-jdk-type="Python SDK" />
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (corrscope-py3.7)" project-jdk-type="Python SDK" />
|
||||
</project>
|
|
@ -2,7 +2,7 @@
|
|||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/ovgenpy.iml" filepath="$PROJECT_DIR$/.idea/ovgenpy.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/corrscope.iml" filepath="$PROJECT_DIR$/.idea/corrscope.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -1,4 +1,4 @@
|
|||
from ovgenpy import cli
|
||||
from corrscope import cli
|
||||
|
||||
if __name__ == '__main__':
|
||||
cli.main()
|
|
@ -4,13 +4,13 @@ from typing import TYPE_CHECKING, Optional, Union
|
|||
import attr
|
||||
from ruamel.yaml.comments import CommentedMap
|
||||
|
||||
from ovgenpy.config import register_config, Alias, OvgenError
|
||||
from ovgenpy.triggers import ITriggerConfig
|
||||
from ovgenpy.util import coalesce
|
||||
from ovgenpy.wave import _WaveConfig, Wave
|
||||
from corrscope.config import register_config, Alias, CorrError
|
||||
from corrscope.triggers import ITriggerConfig
|
||||
from corrscope.util import coalesce
|
||||
from corrscope.wave import _WaveConfig, Wave
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ovgenpy.ovgenpy import Config
|
||||
from corrscope.corrscope import Config
|
||||
|
||||
|
||||
@register_config
|
||||
|
@ -33,29 +33,29 @@ class ChannelConfig:
|
|||
|
||||
|
||||
class Channel:
|
||||
# trigger_samp is unneeded, since __init__ (not Ovgenpy) constructs triggers.
|
||||
# trigger_samp is unneeded, since __init__ (not CorrScope) constructs triggers.
|
||||
render_samp: int
|
||||
# TODO add a "get_around" method for rendering (also helps test_channel_subsampling)
|
||||
# Currently Ovgenpy peeks at Chanel.render_samp and render_stride (bad).
|
||||
# Currently CorrScope peeks at Channel.render_samp and render_stride (bad).
|
||||
|
||||
# Product of ovgen_cfg.trigger/render_subsampling and trigger/render_width.
|
||||
# Product of corr_cfg.trigger/render_subsampling and trigger/render_width.
|
||||
trigger_stride: int
|
||||
render_stride: int
|
||||
|
||||
def __init__(self, cfg: ChannelConfig, ovgen_cfg: 'Config'):
|
||||
def __init__(self, cfg: ChannelConfig, corr_cfg: 'Config'):
|
||||
self.cfg = cfg
|
||||
|
||||
# Create a Wave object.
|
||||
wcfg = _WaveConfig(amplification=ovgen_cfg.amplification * cfg.ampl_ratio)
|
||||
wcfg = _WaveConfig(amplification=corr_cfg.amplification * cfg.ampl_ratio)
|
||||
self.wave = Wave(wcfg, abspath(cfg.wav_path))
|
||||
|
||||
# `subsampling` increases `stride` and decreases `nsamp`.
|
||||
# `width` increases `stride` without changing `nsamp`.
|
||||
tsub = ovgen_cfg.trigger_subsampling
|
||||
tw = coalesce(cfg.trigger_width, ovgen_cfg.trigger_width)
|
||||
tsub = corr_cfg.trigger_subsampling
|
||||
tw = coalesce(cfg.trigger_width, corr_cfg.trigger_width)
|
||||
|
||||
rsub = ovgen_cfg.render_subsampling
|
||||
rw = coalesce(cfg.render_width, ovgen_cfg.render_width)
|
||||
rsub = corr_cfg.render_subsampling
|
||||
rw = coalesce(cfg.render_width, corr_cfg.render_width)
|
||||
|
||||
# nsamp = orig / subsampling
|
||||
# stride = subsampling * width
|
||||
|
@ -63,8 +63,8 @@ class Channel:
|
|||
width_s = width_ms / 1000
|
||||
return round(width_s * self.wave.smp_s / sub)
|
||||
|
||||
trigger_samp = calculate_nsamp(ovgen_cfg.trigger_ms, tsub)
|
||||
self.render_samp = calculate_nsamp(ovgen_cfg.render_ms, rsub)
|
||||
trigger_samp = calculate_nsamp(corr_cfg.trigger_ms, tsub)
|
||||
self.render_samp = calculate_nsamp(corr_cfg.render_ms, rsub)
|
||||
|
||||
self.trigger_stride = tsub * tw
|
||||
self.render_stride = rsub * rw
|
||||
|
@ -73,11 +73,11 @@ class Channel:
|
|||
if isinstance(cfg.trigger, ITriggerConfig):
|
||||
tcfg = cfg.trigger
|
||||
elif isinstance(cfg.trigger, (CommentedMap, dict)): # CommentedMap may/not be subclass of dict.
|
||||
tcfg = attr.evolve(ovgen_cfg.trigger, **cfg.trigger)
|
||||
tcfg = attr.evolve(corr_cfg.trigger, **cfg.trigger)
|
||||
elif cfg.trigger is None:
|
||||
tcfg = ovgen_cfg.trigger
|
||||
tcfg = corr_cfg.trigger
|
||||
else:
|
||||
raise OvgenError(
|
||||
raise CorrError(
|
||||
f'invalid per-channel trigger {cfg.trigger}, type={type(cfg.trigger)}, '
|
||||
f'must be (*)TriggerConfig, dict, or None')
|
||||
|
||||
|
@ -85,6 +85,6 @@ class Channel:
|
|||
wave=self.wave,
|
||||
tsamp=trigger_samp,
|
||||
stride=self.trigger_stride,
|
||||
fps=ovgen_cfg.fps
|
||||
fps=corr_cfg.fps
|
||||
)
|
||||
|
|
@ -4,10 +4,10 @@ from typing import Optional, List, Tuple, Union
|
|||
|
||||
import click
|
||||
|
||||
from ovgenpy.channel import ChannelConfig
|
||||
from ovgenpy.config import yaml
|
||||
from ovgenpy.outputs import IOutputConfig, FFplayOutputConfig, FFmpegOutputConfig
|
||||
from ovgenpy.ovgenpy import default_config, Ovgen, Config, Arguments
|
||||
from corrscope.channel import ChannelConfig
|
||||
from corrscope.config import yaml
|
||||
from corrscope.outputs import IOutputConfig, FFplayOutputConfig, FFmpegOutputConfig
|
||||
from corrscope.corrscope import default_config, CorrScope, Config, Arguments
|
||||
|
||||
|
||||
Folder = click.Path(exists=True, file_okay=False)
|
||||
|
@ -36,7 +36,7 @@ YAML_NAME = YAML_EXTS[0]
|
|||
VIDEO_NAME = '.mp4'
|
||||
|
||||
|
||||
DEFAULT_NAME = 'ovgenpy'
|
||||
DEFAULT_NAME = 'corrscope'
|
||||
def get_name(audio_file: Union[None, str, Path]) -> str:
|
||||
# Write file to current working dir, not audio dir.
|
||||
if audio_file:
|
||||
|
@ -91,15 +91,15 @@ def main(
|
|||
.yaml config.
|
||||
"""
|
||||
# GUI:
|
||||
# ovgenpy
|
||||
# ovgenpy file.yaml
|
||||
# ovgenpy wildcard/wav/folder ... [--options]
|
||||
# corrscope
|
||||
# corrscope file.yaml
|
||||
# corrscope wildcard/wav/folder ... [--options]
|
||||
#
|
||||
# CLI:
|
||||
# ovgenpy wildcard/wav/folder ... [--options] --write-cfg file.yaml [--play]
|
||||
# ovgenpy wildcard/wav/folder ... --play
|
||||
# ovgenpy file.yaml --play
|
||||
# ovgenpy file.yaml --write-yaml
|
||||
# corrscope wildcard/wav/folder ... [--options] --write-cfg file.yaml [--play]
|
||||
# corrscope wildcard/wav/folder ... --play
|
||||
# corrscope file.yaml --play
|
||||
# corrscope file.yaml --write-yaml
|
||||
#
|
||||
# - You can specify as many wildcards or wav files as you want.
|
||||
# - You can only supply one folder, with no files/wildcards.
|
||||
|
@ -164,7 +164,7 @@ def main(
|
|||
cfg_dir = '.'
|
||||
|
||||
if show_gui:
|
||||
from ovgenpy import gui
|
||||
from corrscope import gui
|
||||
gui.gui_main(cfg, cfg_path)
|
||||
|
||||
else:
|
||||
|
@ -184,9 +184,9 @@ def main(
|
|||
outputs.append(FFmpegOutputConfig(video_path))
|
||||
|
||||
if outputs:
|
||||
assert Ovgen # to prevent PyCharm from deleting the import
|
||||
assert CorrScope # to prevent PyCharm from deleting the import
|
||||
arg = Arguments(cfg_dir=cfg_dir, outputs=outputs)
|
||||
command = lambda: Ovgen(cfg, arg).play()
|
||||
command = lambda: CorrScope(cfg, arg).play()
|
||||
if profile:
|
||||
import cProfile
|
||||
|
|
@ -11,7 +11,7 @@ if TYPE_CHECKING:
|
|||
|
||||
__all__ = ['yaml', 'copy_config',
|
||||
'register_config', 'kw_config', 'Alias', 'Ignored', 'register_enum',
|
||||
'OvgenError', 'OvgenWarning']
|
||||
'CorrError', 'CorrWarning']
|
||||
|
||||
|
||||
# Setup YAML loading (yaml object).
|
||||
|
@ -148,7 +148,7 @@ class _ConfigMixin:
|
|||
if isinstance(class_var, Alias):
|
||||
target = class_var.key
|
||||
if target in state:
|
||||
raise OvgenError(
|
||||
raise CorrError(
|
||||
f'{type(self).__name__} received both Alias {key} and '
|
||||
f'equivalent {target}'
|
||||
)
|
||||
|
@ -189,13 +189,13 @@ class _EnumMixin:
|
|||
|
||||
# Miscellaneous
|
||||
|
||||
class OvgenError(ValueError):
|
||||
class CorrError(ValueError):
|
||||
""" Error caused by invalid end-user input (via YAML/GUI config).
|
||||
(Should be) caught by GUI and displayed to user. """
|
||||
pass
|
||||
|
||||
|
||||
class OvgenWarning(UserWarning):
|
||||
class CorrWarning(UserWarning):
|
||||
""" Warning about deprecated end-user config (YAML/GUI).
|
||||
(Should be) caught by GUI and displayed to user. """
|
||||
pass
|
|
@ -9,17 +9,17 @@ from typing import Optional, List, Union, TYPE_CHECKING, Callable
|
|||
|
||||
import attr
|
||||
|
||||
from ovgenpy import outputs as outputs_
|
||||
from ovgenpy.channel import Channel, ChannelConfig
|
||||
from ovgenpy.config import kw_config, register_enum, Ignored, OvgenError, OvgenWarning
|
||||
from ovgenpy.renderer import MatplotlibRenderer, RendererConfig
|
||||
from ovgenpy.layout import LayoutConfig
|
||||
from ovgenpy.triggers import ITriggerConfig, CorrelationTriggerConfig, PerFrameCache
|
||||
from ovgenpy.util import pushd, coalesce
|
||||
from ovgenpy.wave import Wave
|
||||
from corrscope import outputs as outputs_
|
||||
from corrscope.channel import Channel, ChannelConfig
|
||||
from corrscope.config import kw_config, register_enum, Ignored, CorrError, CorrWarning
|
||||
from corrscope.renderer import MatplotlibRenderer, RendererConfig
|
||||
from corrscope.layout import LayoutConfig
|
||||
from corrscope.triggers import ITriggerConfig, CorrelationTriggerConfig, PerFrameCache
|
||||
from corrscope.util import pushd, coalesce
|
||||
from corrscope.wave import Wave
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ovgenpy.triggers import CorrelationTrigger
|
||||
from corrscope.triggers import CorrelationTrigger
|
||||
|
||||
|
||||
PRINT_TIMESTAMP = True
|
||||
|
@ -89,7 +89,7 @@ class Config:
|
|||
if not isinstance(self.benchmark_mode, BenchmarkMode):
|
||||
self.benchmark_mode = BenchmarkMode[self.benchmark_mode]
|
||||
except KeyError:
|
||||
raise OvgenError(
|
||||
raise CorrError(
|
||||
f'invalid benchmark_mode mode {self.benchmark_mode} not in '
|
||||
f'{[el.name for el in BenchmarkMode]}')
|
||||
|
||||
|
@ -104,7 +104,7 @@ class Config:
|
|||
self.trigger_ms = coalesce(self.trigger_ms, width_ms)
|
||||
self.render_ms = coalesce(self.render_ms, width_ms)
|
||||
except TypeError:
|
||||
raise OvgenError(
|
||||
raise CorrError(
|
||||
'Must supply either width_ms or both (trigger_ms and render_ms)')
|
||||
|
||||
deprecated = []
|
||||
|
@ -114,7 +114,7 @@ class Config:
|
|||
deprecated.append('render_width')
|
||||
if deprecated:
|
||||
warnings.warn(f"Options {deprecated} are deprecated and will be removed",
|
||||
OvgenWarning)
|
||||
CorrWarning)
|
||||
|
||||
|
||||
_FPS = 60 # f_s
|
||||
|
@ -161,7 +161,7 @@ class Arguments:
|
|||
is_aborted: IsAborted = lambda: False
|
||||
on_end: Callable[[], None] = lambda: None
|
||||
|
||||
class Ovgen:
|
||||
class CorrScope:
|
||||
def __init__(self, cfg: Config, arg: Arguments):
|
||||
self.cfg = cfg
|
||||
self.arg = arg
|
||||
|
@ -178,7 +178,7 @@ class Ovgen:
|
|||
self.output_cfgs = []
|
||||
|
||||
if len(self.cfg.channels) == 0:
|
||||
raise OvgenError('Config.channels is empty')
|
||||
raise CorrError('Config.channels is empty')
|
||||
|
||||
waves: List[Wave]
|
||||
channels: List[Channel]
|
||||
|
@ -209,7 +209,7 @@ class Ovgen:
|
|||
|
||||
def play(self):
|
||||
if self.has_played:
|
||||
raise ValueError('Cannot call Ovgen.play() more than once')
|
||||
raise ValueError('Cannot call CorrScope.play() more than once')
|
||||
self.has_played = True
|
||||
|
||||
self._load_channels()
|
||||
|
@ -231,16 +231,16 @@ class Ovgen:
|
|||
internals = self.cfg.show_internals
|
||||
extra_outputs = SimpleNamespace()
|
||||
if internals:
|
||||
from ovgenpy.outputs import FFplayOutputConfig
|
||||
from corrscope.outputs import FFplayOutputConfig
|
||||
import attr
|
||||
|
||||
no_audio = attr.evolve(self.cfg, master_audio='')
|
||||
|
||||
ovgen = self
|
||||
corr = self
|
||||
|
||||
class RenderOutput:
|
||||
def __init__(self):
|
||||
self.renderer = ovgen._load_renderer()
|
||||
self.renderer = corr._load_renderer()
|
||||
self.output = FFplayOutputConfig()(no_audio)
|
||||
|
||||
def render_frame(self, datas):
|
|
@ -12,19 +12,19 @@ from PyQt5.QtCore import QModelIndex, Qt
|
|||
from PyQt5.QtGui import QKeySequence, QFont, QCloseEvent
|
||||
from PyQt5.QtWidgets import QShortcut
|
||||
|
||||
from ovgenpy import cli
|
||||
from ovgenpy.channel import ChannelConfig
|
||||
from ovgenpy.config import OvgenError, copy_config, yaml
|
||||
from ovgenpy.gui.data_bind import PresentationModel, map_gui, behead, rgetattr, rsetattr
|
||||
from ovgenpy.gui.util import color2hex, Locked, get_save_with_ext, find_ranges
|
||||
from ovgenpy.outputs import IOutputConfig, FFplayOutputConfig, FFmpegOutputConfig
|
||||
from ovgenpy.ovgenpy import Ovgen, Config, Arguments, default_config
|
||||
from ovgenpy.triggers import CorrelationTriggerConfig, ITriggerConfig
|
||||
from ovgenpy.util import obj_name
|
||||
from corrscope import cli
|
||||
from corrscope.channel import ChannelConfig
|
||||
from corrscope.config import CorrError, copy_config, yaml
|
||||
from corrscope.gui.data_bind import PresentationModel, map_gui, behead, rgetattr, rsetattr
|
||||
from corrscope.gui.util import color2hex, Locked, get_save_with_ext, find_ranges
|
||||
from corrscope.outputs import IOutputConfig, FFplayOutputConfig, FFmpegOutputConfig
|
||||
from corrscope.corrscope import CorrScope, Config, Arguments, default_config
|
||||
from corrscope.triggers import CorrelationTriggerConfig, ITriggerConfig
|
||||
from corrscope.util import obj_name
|
||||
|
||||
FILTER_WAV_FILES = "WAV files (*.wav)"
|
||||
|
||||
APP_NAME = 'ovgenpy'
|
||||
APP_NAME = 'corrscope'
|
||||
APP_DIR = Path(__file__).parent
|
||||
|
||||
def res(file: str) -> str:
|
||||
|
@ -88,8 +88,8 @@ class MainWindow(qw.QMainWindow):
|
|||
self.actionRender.triggered.connect(self.on_action_render)
|
||||
self.actionExit.triggered.connect(qw.QApplication.closeAllWindows)
|
||||
|
||||
# Initialize ovgen-thread attribute.
|
||||
self.ovgen_thread: Locked[Optional[OvgenThread]] = Locked(None)
|
||||
# Initialize CorrScope-thread attribute.
|
||||
self.corr_thread: Locked[Optional[CorrThread]] = Locked(None)
|
||||
|
||||
# Bind config to UI.
|
||||
self.load_cfg(cfg, cfg_path)
|
||||
|
@ -273,11 +273,11 @@ class MainWindow(qw.QMainWindow):
|
|||
return False
|
||||
|
||||
def on_action_play(self):
|
||||
""" Launch ovgen and ffplay. """
|
||||
""" Launch CorrScope and ffplay. """
|
||||
error_msg = 'Cannot play, another play/render is active'
|
||||
with self.ovgen_thread as t:
|
||||
with self.corr_thread as t:
|
||||
if t is not None:
|
||||
self.ovgen_thread.unlock()
|
||||
self.corr_thread.unlock()
|
||||
qw.QMessageBox.critical(self, 'Error', error_msg)
|
||||
return
|
||||
|
||||
|
@ -287,9 +287,9 @@ class MainWindow(qw.QMainWindow):
|
|||
def on_action_render(self):
|
||||
""" Get file name. Then show a progress dialog while rendering to file. """
|
||||
error_msg = 'Cannot render to file, another play/render is active'
|
||||
with self.ovgen_thread as t:
|
||||
with self.corr_thread as t:
|
||||
if t is not None:
|
||||
self.ovgen_thread.unlock()
|
||||
self.corr_thread.unlock()
|
||||
qw.QMessageBox.critical(self, 'Error', error_msg)
|
||||
return
|
||||
|
||||
|
@ -300,14 +300,14 @@ class MainWindow(qw.QMainWindow):
|
|||
if path:
|
||||
name = str(path)
|
||||
# FIXME what if missing mp4?
|
||||
dlg = OvgenProgressDialog(self, 'Rendering video')
|
||||
dlg = CorrProgressDialog(self, 'Rendering video')
|
||||
|
||||
outputs = [FFmpegOutputConfig(name)]
|
||||
self.play_thread(outputs, dlg)
|
||||
|
||||
def play_thread(self, outputs: List[IOutputConfig],
|
||||
dlg: Optional['OvgenProgressDialog']):
|
||||
""" self.ovgen_thread MUST be locked. """
|
||||
dlg: Optional['CorrProgressDialog']):
|
||||
""" self.corr_thread MUST be locked. """
|
||||
arg = self._get_args(outputs)
|
||||
if dlg:
|
||||
arg = attr.evolve(arg,
|
||||
|
@ -318,7 +318,7 @@ class MainWindow(qw.QMainWindow):
|
|||
)
|
||||
|
||||
cfg = copy_config(self.model.cfg)
|
||||
t = self.ovgen_thread.obj = OvgenThread(cfg, arg)
|
||||
t = self.corr_thread.obj = CorrThread(cfg, arg)
|
||||
t.error.connect(self.on_play_thread_error)
|
||||
t.finished.connect(self.on_play_thread_finished)
|
||||
t.start()
|
||||
|
@ -327,7 +327,7 @@ class MainWindow(qw.QMainWindow):
|
|||
qw.QMessageBox.critical(self, 'Error rendering oscilloscope', str(exc))
|
||||
|
||||
def on_play_thread_finished(self):
|
||||
self.ovgen_thread.set(None)
|
||||
self.corr_thread.set(None)
|
||||
|
||||
def _get_args(self, outputs: List[IOutputConfig]):
|
||||
arg = Arguments(
|
||||
|
@ -376,7 +376,7 @@ class ShortcutButton(qw.QPushButton):
|
|||
self.setToolTip(keys.toString(QKeySequence.NativeText))
|
||||
|
||||
|
||||
class OvgenThread(qc.QThread):
|
||||
class CorrThread(qc.QThread):
|
||||
def __init__(self, cfg: Config, arg: Arguments):
|
||||
qc.QThread.__init__(self)
|
||||
self.cfg = cfg
|
||||
|
@ -386,7 +386,7 @@ class OvgenThread(qc.QThread):
|
|||
cfg = self.cfg
|
||||
arg = self.arg
|
||||
try:
|
||||
Ovgen(cfg, arg).play()
|
||||
CorrScope(cfg, arg).play()
|
||||
except Exception as e:
|
||||
arg.on_end()
|
||||
self.error.emit(e)
|
||||
|
@ -396,7 +396,7 @@ class OvgenThread(qc.QThread):
|
|||
error = qc.pyqtSignal(Exception)
|
||||
|
||||
|
||||
class OvgenProgressDialog(qw.QProgressDialog):
|
||||
class CorrProgressDialog(qw.QProgressDialog):
|
||||
def __init__(self, parent: Optional[qw.QWidget], title: str):
|
||||
super().__init__(parent)
|
||||
self.setMinimumWidth(300)
|
||||
|
@ -409,12 +409,12 @@ class OvgenProgressDialog(qw.QProgressDialog):
|
|||
# Don't reset when rendering is approximately finished.
|
||||
self.setAutoReset(False)
|
||||
|
||||
# Close after ovgen finishes.
|
||||
# Close after CorrScope finishes.
|
||||
self.setAutoClose(True)
|
||||
|
||||
def on_begin(self, begin_time, end_time):
|
||||
self.setRange(int(round(begin_time)), int(round(end_time)))
|
||||
# self.setValue is called by Ovgen, on the first frame.
|
||||
# self.setValue is called by CorrScope, on the first frame.
|
||||
|
||||
|
||||
def nrow_ncol_property(altered: str, unaltered: str) -> property:
|
||||
|
@ -433,7 +433,7 @@ def nrow_ncol_property(altered: str, unaltered: str) -> property:
|
|||
elif val == 0:
|
||||
setattr(self.cfg.layout, altered, None)
|
||||
else:
|
||||
raise OvgenError(f"invalid input: {altered} < 0, should never happen")
|
||||
raise CorrError(f"invalid input: {altered} < 0, should never happen")
|
||||
|
||||
return property(get, set)
|
||||
|
||||
|
@ -480,7 +480,7 @@ class ConfigModel(PresentationModel):
|
|||
|
||||
@render_video_size.setter
|
||||
def render_video_size(self, value: str):
|
||||
error = OvgenError(f"invalid video size {value}, must be WxH")
|
||||
error = CorrError(f"invalid video size {value}, must be WxH")
|
||||
|
||||
for sep in 'x*,':
|
||||
width_height = value.split(sep)
|
||||
|
@ -592,7 +592,7 @@ class ChannelModel(qc.QAbstractTableModel):
|
|||
t = cfg.trigger
|
||||
if isinstance(t, ITriggerConfig):
|
||||
if not isinstance(t, CorrelationTriggerConfig):
|
||||
raise OvgenError(
|
||||
raise CorrError(
|
||||
f'Loading per-channel {obj_name(t)} not supported')
|
||||
trigger_dict = attr.asdict(t)
|
||||
else:
|
|
@ -7,12 +7,12 @@ from PyQt5.QtCore import pyqtSlot
|
|||
from PyQt5.QtGui import QPalette, QColor
|
||||
from PyQt5.QtWidgets import QWidget
|
||||
|
||||
from ovgenpy.config import OvgenError
|
||||
from ovgenpy.triggers import lerp
|
||||
from ovgenpy.util import obj_name, perr
|
||||
from corrscope.config import CorrError
|
||||
from corrscope.triggers import lerp
|
||||
from corrscope.util import obj_name, perr
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ovgenpy.gui import MainWindow
|
||||
from corrscope.gui import MainWindow
|
||||
|
||||
__all__ = ['PresentationModel', 'map_gui', 'behead', 'rgetattr', 'rsetattr']
|
||||
|
||||
|
@ -158,7 +158,7 @@ def model_setter(value_type: type) -> Callable:
|
|||
assert isinstance(value, value_type)
|
||||
try:
|
||||
self.pmodel[self.path] = value
|
||||
except OvgenError:
|
||||
except CorrError:
|
||||
self.setPalette(self.error_palette)
|
||||
else:
|
||||
self.setPalette(self.default_palette)
|
|
@ -550,32 +550,32 @@
|
|||
<customwidget>
|
||||
<class>BoundLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>ovgenpy/gui/data_bind.h</header>
|
||||
<header>corrscope/gui/data_bind.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>BoundSpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>ovgenpy/gui/data_bind.h</header>
|
||||
<header>corrscope/gui/data_bind.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>BoundDoubleSpinBox</class>
|
||||
<extends>QDoubleSpinBox</extends>
|
||||
<header>ovgenpy/gui/data_bind.h</header>
|
||||
<header>corrscope/gui/data_bind.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>BoundComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>ovgenpy/gui/data_bind.h</header>
|
||||
<header>corrscope/gui/data_bind.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ShortcutButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>ovgenpy/gui/__init__.h</header>
|
||||
<header>corrscope/gui/__init__.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ChannelTableView</class>
|
||||
<extends>QTableView</extends>
|
||||
<header>ovgenpy/gui/__init__.h</header>
|
||||
<header>corrscope/gui/__init__.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
|
@ -7,16 +7,16 @@ import more_itertools
|
|||
from PyQt5.QtCore import QMutex
|
||||
from PyQt5.QtWidgets import QWidget, QFileDialog
|
||||
|
||||
from ovgenpy.config import OvgenError
|
||||
from corrscope.config import CorrError
|
||||
|
||||
|
||||
def color2hex(color):
|
||||
try:
|
||||
return matplotlib.colors.to_hex(color, keep_alpha=False)
|
||||
except ValueError:
|
||||
raise OvgenError(f'invalid color {color}')
|
||||
raise CorrError(f'invalid color {color}')
|
||||
except Exception as e:
|
||||
raise OvgenError(
|
||||
raise CorrError(
|
||||
f'doubly invalid color {color}, raises {e} (report bug!)')
|
||||
|
||||
|
|
@ -2,8 +2,8 @@ from typing import Optional, TypeVar, Callable, List
|
|||
|
||||
import numpy as np
|
||||
|
||||
from ovgenpy.config import register_config, OvgenError
|
||||
from ovgenpy.util import ceildiv
|
||||
from corrscope.config import register_config, CorrError
|
||||
from corrscope.util import ceildiv
|
||||
|
||||
|
||||
@register_config(always_dump='orientation')
|
||||
|
@ -19,7 +19,7 @@ class LayoutConfig:
|
|||
self.ncols = None
|
||||
|
||||
if self.nrows and self.ncols:
|
||||
raise OvgenError('cannot manually assign both nrows and ncols')
|
||||
raise CorrError('cannot manually assign both nrows and ncols')
|
||||
|
||||
if not self.nrows and not self.ncols:
|
||||
self.ncols = 1
|
||||
|
@ -41,7 +41,7 @@ class RendererLayout:
|
|||
|
||||
self.orientation = cfg.orientation
|
||||
if self.orientation not in self.VALID_ORIENTATIONS:
|
||||
raise OvgenError(f'Invalid orientation {self.orientation} not in '
|
||||
raise CorrError(f'Invalid orientation {self.orientation} not in '
|
||||
f'{self.VALID_ORIENTATIONS}')
|
||||
|
||||
def _calc_layout(self):
|
|
@ -6,10 +6,10 @@ from abc import ABC, abstractmethod
|
|||
from os.path import abspath
|
||||
from typing import TYPE_CHECKING, Type, List, Union, Optional
|
||||
|
||||
from ovgenpy.config import register_config
|
||||
from corrscope.config import register_config
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ovgenpy.ovgenpy import Config
|
||||
from corrscope.corrscope import Config
|
||||
|
||||
|
||||
ByteBuffer = Union[bytes, np.ndarray]
|
||||
|
@ -22,8 +22,8 @@ FRAMES_TO_BUFFER = 2
|
|||
class IOutputConfig:
|
||||
cls: 'Type[Output]'
|
||||
|
||||
def __call__(self, ovgen_cfg: 'Config'):
|
||||
return self.cls(ovgen_cfg, cfg=self)
|
||||
def __call__(self, corr_cfg: 'Config'):
|
||||
return self.cls(corr_cfg, cfg=self)
|
||||
|
||||
|
||||
class _Stop:
|
||||
|
@ -34,11 +34,11 @@ Stop = _Stop()
|
|||
|
||||
|
||||
class Output(ABC):
|
||||
def __init__(self, ovgen_cfg: 'Config', cfg: IOutputConfig):
|
||||
self.ovgen_cfg = ovgen_cfg
|
||||
def __init__(self, corr_cfg: 'Config', cfg: IOutputConfig):
|
||||
self.corr_cfg = corr_cfg
|
||||
self.cfg = cfg
|
||||
|
||||
rcfg = ovgen_cfg.render
|
||||
rcfg = corr_cfg.render
|
||||
|
||||
frame_bytes = rcfg.height * rcfg.width * RGB_DEPTH
|
||||
self.bufsize = frame_bytes * FRAMES_TO_BUFFER
|
||||
|
@ -69,26 +69,26 @@ def register_output(config_t: Type[IOutputConfig]):
|
|||
# FFmpeg command line generation
|
||||
|
||||
class _FFmpegProcess:
|
||||
def __init__(self, templates: List[str], ovgen_cfg: 'Config'):
|
||||
def __init__(self, templates: List[str], corr_cfg: 'Config'):
|
||||
self.templates = templates
|
||||
self.ovgen_cfg = ovgen_cfg
|
||||
self.corr_cfg = corr_cfg
|
||||
|
||||
self.templates += ffmpeg_input_video(ovgen_cfg) # video
|
||||
if ovgen_cfg.master_audio:
|
||||
self.templates += ffmpeg_input_video(corr_cfg) # video
|
||||
if corr_cfg.master_audio:
|
||||
# Load master audio and trim to timestamps.
|
||||
|
||||
self.templates.append(f'-ss {ovgen_cfg.begin_time}')
|
||||
self.templates.append(f'-ss {corr_cfg.begin_time}')
|
||||
|
||||
audio_path = shlex.quote(abspath(ovgen_cfg.master_audio))
|
||||
audio_path = shlex.quote(abspath(corr_cfg.master_audio))
|
||||
self.templates += ffmpeg_input_audio(audio_path) # audio
|
||||
|
||||
if ovgen_cfg.end_time is not None:
|
||||
dur = ovgen_cfg.end_time - ovgen_cfg.begin_time
|
||||
if corr_cfg.end_time is not None:
|
||||
dur = corr_cfg.end_time - corr_cfg.begin_time
|
||||
self.templates.append(f'-to {dur}')
|
||||
|
||||
def add_output(self, cfg: 'Union[FFmpegOutputConfig, FFplayOutputConfig]') -> None:
|
||||
self.templates.append(cfg.video_template) # video
|
||||
if self.ovgen_cfg.master_audio:
|
||||
if self.corr_cfg.master_audio:
|
||||
self.templates.append(cfg.audio_template) # audio
|
||||
|
||||
def popen(self, extra_args, bufsize, **kwargs) -> subprocess.Popen:
|
||||
|
@ -193,10 +193,10 @@ FFMPEG = 'ffmpeg'
|
|||
|
||||
@register_output(FFmpegOutputConfig)
|
||||
class FFmpegOutput(PipeOutput):
|
||||
def __init__(self, ovgen_cfg: 'Config', cfg: FFmpegOutputConfig):
|
||||
super().__init__(ovgen_cfg, cfg)
|
||||
def __init__(self, corr_cfg: 'Config', cfg: FFmpegOutputConfig):
|
||||
super().__init__(corr_cfg, cfg)
|
||||
|
||||
ffmpeg = _FFmpegProcess([FFMPEG, '-y'], ovgen_cfg)
|
||||
ffmpeg = _FFmpegProcess([FFMPEG, '-y'], corr_cfg)
|
||||
ffmpeg.add_output(cfg)
|
||||
ffmpeg.templates.append(cfg.args)
|
||||
|
||||
|
@ -220,10 +220,10 @@ FFPLAY = 'ffplay'
|
|||
|
||||
@register_output(FFplayOutputConfig)
|
||||
class FFplayOutput(PipeOutput):
|
||||
def __init__(self, ovgen_cfg: 'Config', cfg: FFplayOutputConfig):
|
||||
super().__init__(ovgen_cfg, cfg)
|
||||
def __init__(self, corr_cfg: 'Config', cfg: FFplayOutputConfig):
|
||||
super().__init__(corr_cfg, cfg)
|
||||
|
||||
ffmpeg = _FFmpegProcess([FFMPEG, '-nostats'], ovgen_cfg)
|
||||
ffmpeg = _FFmpegProcess([FFMPEG, '-nostats'], corr_cfg)
|
||||
ffmpeg.add_output(cfg)
|
||||
ffmpeg.templates.append('-f nut')
|
||||
|
|
@ -5,10 +5,10 @@ import matplotlib
|
|||
import numpy as np
|
||||
import attr
|
||||
|
||||
from ovgenpy.config import register_config
|
||||
from ovgenpy.layout import RendererLayout, LayoutConfig
|
||||
from ovgenpy.outputs import RGB_DEPTH, ByteBuffer
|
||||
from ovgenpy.util import coalesce
|
||||
from corrscope.config import register_config
|
||||
from corrscope.layout import RendererLayout, LayoutConfig
|
||||
from corrscope.outputs import RGB_DEPTH, ByteBuffer
|
||||
from corrscope.util import coalesce
|
||||
|
||||
matplotlib.use('agg')
|
||||
from matplotlib import pyplot as plt
|
||||
|
@ -18,7 +18,7 @@ if TYPE_CHECKING:
|
|||
from matplotlib.axes import Axes
|
||||
from matplotlib.figure import Figure
|
||||
from matplotlib.lines import Line2D
|
||||
from ovgenpy.channel import ChannelConfig
|
||||
from corrscope.channel import ChannelConfig
|
||||
|
||||
|
||||
def default_color():
|
|
@ -7,14 +7,14 @@ from scipy import signal
|
|||
from scipy.signal import windows
|
||||
import attr
|
||||
|
||||
from ovgenpy.config import kw_config, OvgenError, Alias, OvgenWarning
|
||||
from ovgenpy.util import find, obj_name
|
||||
from ovgenpy.utils.windows import midpad, leftpad
|
||||
from ovgenpy.wave import FLOAT
|
||||
from corrscope.config import kw_config, CorrError, Alias, CorrWarning
|
||||
from corrscope.util import find, obj_name
|
||||
from corrscope.utils.windows import midpad, leftpad
|
||||
from corrscope.wave import FLOAT
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ovgenpy.wave import Wave
|
||||
from corrscope.wave import Wave
|
||||
|
||||
# Abstract classes
|
||||
|
||||
|
@ -133,7 +133,7 @@ class CorrelationTriggerConfig(ITriggerConfig):
|
|||
warnings.warn(
|
||||
"Ignoring old `CorrelationTriggerConfig.use_edge_trigger` flag, "
|
||||
"overriden by newer `post` flag.",
|
||||
OvgenWarning
|
||||
CorrWarning
|
||||
)
|
||||
else:
|
||||
self.post = ZeroCrossingTriggerConfig()
|
||||
|
@ -141,7 +141,7 @@ class CorrelationTriggerConfig(ITriggerConfig):
|
|||
def _validate_param(self, key: str, begin, end):
|
||||
value = getattr(self, key)
|
||||
if not begin <= value <= end:
|
||||
raise OvgenError(
|
||||
raise CorrError(
|
||||
f'Invalid {key}={value} (should be within [{begin}, {end}])')
|
||||
|
||||
|
||||
|
@ -176,7 +176,7 @@ class CorrelationTrigger(Trigger):
|
|||
|
||||
def _calc_data_taper(self):
|
||||
""" Input data window. Zeroes out all data older than 1 frame old.
|
||||
See https://github.com/nyanpasu64/ovgenpy/wiki/Correlation-Trigger
|
||||
See https://github.com/nyanpasu64/corrscope/wiki/Correlation-Trigger
|
||||
"""
|
||||
N = self._buffer_nsamp
|
||||
halfN = N // 2
|
||||
|
@ -410,12 +410,12 @@ class PostTrigger(Trigger, ABC):
|
|||
Trigger.__init__(self, *args, **kwargs)
|
||||
|
||||
if self._stride != 1:
|
||||
raise OvgenError(
|
||||
raise CorrError(
|
||||
f'{obj_name(self)} with stride != 1 is not allowed '
|
||||
f'(supplied {self._stride})')
|
||||
|
||||
if self.post:
|
||||
raise OvgenError(
|
||||
raise CorrError(
|
||||
f'Passing {obj_name(self)} a post_trigger is not allowed '
|
||||
f'({obj_name(self.post)})'
|
||||
)
|
||||
|
@ -457,7 +457,7 @@ class LocalPostTrigger(PostTrigger):
|
|||
|
||||
# Window data
|
||||
if cache.period is None:
|
||||
raise OvgenError(
|
||||
raise CorrError(
|
||||
"Missing 'cache.period', try stacking CorrelationTrigger "
|
||||
"before LocalPostTrigger")
|
||||
|
|
@ -6,7 +6,7 @@ from scipy.io import wavfile
|
|||
|
||||
|
||||
# Internal class, not exposed via YAML
|
||||
from ovgenpy.config import OvgenError
|
||||
from corrscope.config import CorrError
|
||||
|
||||
|
||||
@attr.dataclass
|
||||
|
@ -54,7 +54,7 @@ class Wave:
|
|||
self.max_val = 1
|
||||
|
||||
else:
|
||||
raise OvgenError(f'unexpected wavfile dtype {dtype}')
|
||||
raise CorrError(f'unexpected wavfile dtype {dtype}')
|
||||
|
||||
def __getitem__(self, index: Union[int, slice]) -> 'np.ndarray[FLOAT]':
|
||||
""" Copies self.data[item], converted to a FLOAT within range [-1, 1). """
|
|
@ -4,4 +4,4 @@ testpaths = tests
|
|||
[coverage:run]
|
||||
branch = True
|
||||
source =
|
||||
ovgenpy
|
||||
corrscope
|
||||
|
|
6
setup.py
6
setup.py
|
@ -1,10 +1,10 @@
|
|||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
name='ovgenpy',
|
||||
name='corrscope',
|
||||
version='0',
|
||||
packages=['ovgenpy'],
|
||||
url='https://github.com/nyanpasu64/ovgenpy',
|
||||
packages=['corrscope'],
|
||||
url='https://github.com/nyanpasu64/corrscope',
|
||||
license='BSD-2-Clause',
|
||||
author='nyanpasu64',
|
||||
author_email='',
|
||||
|
|
|
@ -6,13 +6,13 @@ from hypothesis import given
|
|||
import hypothesis.strategies as hs
|
||||
from pytest_mock import MockFixture
|
||||
|
||||
import ovgenpy.channel
|
||||
import ovgenpy.ovgenpy
|
||||
from ovgenpy.channel import ChannelConfig, Channel
|
||||
from ovgenpy.config import OvgenError
|
||||
from ovgenpy.ovgenpy import default_config, Ovgen, BenchmarkMode, Arguments
|
||||
from ovgenpy.triggers import NullTriggerConfig
|
||||
from ovgenpy.util import coalesce
|
||||
import corrscope.channel
|
||||
import corrscope.corrscope
|
||||
from corrscope.channel import ChannelConfig, Channel
|
||||
from corrscope.config import CorrError
|
||||
from corrscope.corrscope import default_config, CorrScope, BenchmarkMode, Arguments
|
||||
from corrscope.triggers import NullTriggerConfig
|
||||
from corrscope.util import coalesce
|
||||
|
||||
|
||||
positive = hs.integers(min_value=1, max_value=100)
|
||||
|
@ -23,7 +23,7 @@ maybe = hs.one_of(hs.none(), positive)
|
|||
Maybe = Optional[int]
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings("ignore::ovgenpy.config.OvgenWarning")
|
||||
@pytest.mark.filterwarnings("ignore::corrscope.config.CorrWarning")
|
||||
@given(
|
||||
# Channel
|
||||
c_trigger_width=maybe, c_render_width=maybe,
|
||||
|
@ -53,9 +53,9 @@ def test_config_channel_width_stride(
|
|||
"""
|
||||
|
||||
# region setup test variables
|
||||
ovgenpy.ovgenpy.PRINT_TIMESTAMP = False # Cleanup Hypothesis testing logs
|
||||
corrscope.corrscope.PRINT_TIMESTAMP = False # Cleanup Hypothesis testing logs
|
||||
|
||||
Wave = mocker.patch.object(ovgenpy.channel, 'Wave')
|
||||
Wave = mocker.patch.object(corrscope.channel, 'Wave')
|
||||
wave = Wave.return_value
|
||||
|
||||
def get_around(sample: int, region_nsamp: int, stride: int):
|
||||
|
@ -90,7 +90,7 @@ def test_config_channel_width_stride(
|
|||
# endregion
|
||||
|
||||
if not (width_ms or (trigger_ms and render_ms)):
|
||||
with pytest.raises(OvgenError):
|
||||
with pytest.raises(CorrError):
|
||||
_cfg = get_cfg()
|
||||
return
|
||||
|
||||
|
@ -123,10 +123,10 @@ def test_config_channel_width_stride(
|
|||
assert trigger._tsamp == ideal_tsamp
|
||||
assert trigger._stride == channel.trigger_stride
|
||||
|
||||
## Ensure ovgenpy calls render using channel.render_samp and render_stride.
|
||||
ovgen = Ovgen(cfg, Arguments(cfg_dir='.', outputs=[]))
|
||||
renderer = mocker.patch.object(Ovgen, '_load_renderer').return_value
|
||||
ovgen.play()
|
||||
## Ensure corrscope calls render using channel.render_samp and render_stride.
|
||||
corr = CorrScope(cfg, Arguments(cfg_dir='.', outputs=[]))
|
||||
renderer = mocker.patch.object(CorrScope, '_load_renderer').return_value
|
||||
corr.play()
|
||||
|
||||
# Only render (not NullTrigger) calls wave.get_around().
|
||||
(_sample, _region_nsamp, _subsampling), kwargs = wave.get_around.call_args
|
||||
|
|
|
@ -7,13 +7,13 @@ import click
|
|||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
import ovgenpy.channel
|
||||
from ovgenpy import cli
|
||||
from ovgenpy.cli import YAML_NAME
|
||||
from ovgenpy.config import yaml
|
||||
from ovgenpy.outputs import FFmpegOutputConfig
|
||||
from ovgenpy.ovgenpy import Config, Ovgen, Arguments
|
||||
from ovgenpy.util import pushd
|
||||
import corrscope.channel
|
||||
from corrscope import cli
|
||||
from corrscope.cli import YAML_NAME
|
||||
from corrscope.config import yaml
|
||||
from corrscope.outputs import FFmpegOutputConfig
|
||||
from corrscope.corrscope import Config, CorrScope, Arguments
|
||||
from corrscope.util import pushd
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import pytest_mock
|
||||
|
@ -23,7 +23,7 @@ def call_main(argv):
|
|||
return CliRunner().invoke(cli.main, argv, catch_exceptions=False, standalone_mode=False)
|
||||
|
||||
|
||||
# ovgenpy configuration sinks
|
||||
# corrscope configuration sinks
|
||||
|
||||
@pytest.fixture
|
||||
def yaml_sink(mocker: 'pytest_mock.MockFixture') -> Callable:
|
||||
|
@ -45,13 +45,13 @@ def yaml_sink(mocker: 'pytest_mock.MockFixture') -> Callable:
|
|||
@pytest.fixture
|
||||
def player_sink(mocker) -> Callable:
|
||||
def _player_sink(command):
|
||||
Ovgen = mocker.patch.object(cli, 'Ovgen')
|
||||
CorrScope = mocker.patch.object(cli, 'CorrScope')
|
||||
|
||||
argv = shlex.split(command) + ['-p']
|
||||
call_main(argv)
|
||||
|
||||
Ovgen.assert_called_once()
|
||||
args, kwargs = Ovgen.call_args
|
||||
CorrScope.assert_called_once()
|
||||
args, kwargs = CorrScope.call_args
|
||||
cfg = args[0]
|
||||
|
||||
assert isinstance(cfg, Config)
|
||||
|
@ -70,7 +70,7 @@ def any_sink(request, mocker):
|
|||
return sink(mocker)
|
||||
|
||||
|
||||
# ovgenpy configuration sources
|
||||
# corrscope configuration sources
|
||||
|
||||
def test_no_files(any_sink):
|
||||
with pytest.raises(click.ClickException):
|
||||
|
@ -126,14 +126,14 @@ def test_load_yaml_another_dir(yaml_sink, mocker, Popen):
|
|||
|
||||
cfg.begin_time = 100 # To skip all actual rendering
|
||||
|
||||
# Log execution of Ovgen().play()
|
||||
Wave = mocker.spy(ovgenpy.channel, 'Wave')
|
||||
# Log execution of CorrScope().play()
|
||||
Wave = mocker.spy(corrscope.channel, 'Wave')
|
||||
|
||||
# Issue: this test does not use cli.main() to compute output path.
|
||||
# Possible solution: Call cli.main() via Click runner.
|
||||
output = FFmpegOutputConfig(cli.get_path(cfg.master_audio, cli.VIDEO_NAME))
|
||||
ovgen = Ovgen(cfg, Arguments(subdir, [output]))
|
||||
ovgen.play()
|
||||
corr = CorrScope(cfg, Arguments(subdir, [output]))
|
||||
corr.play()
|
||||
|
||||
# Compute absolute paths
|
||||
wav_abs = abspath(f'{subdir}/{wav}')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import pytest
|
||||
from ruamel.yaml import yaml_object
|
||||
|
||||
from ovgenpy.config import register_config, yaml, Alias, Ignored, kw_config, OvgenError
|
||||
from corrscope.config import register_config, yaml, Alias, Ignored, kw_config, CorrError
|
||||
|
||||
# YAML Idiosyncrasies: https://docs.saltstack.com/en/develop/topics/troubleshooting/yaml_idiosyncrasies.html
|
||||
|
||||
|
@ -163,7 +163,7 @@ xx: 1
|
|||
x: 1
|
||||
xx: 1
|
||||
'''
|
||||
with pytest.raises(OvgenError):
|
||||
with pytest.raises(CorrError):
|
||||
yaml.load(s)
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import pytest
|
||||
|
||||
from ovgenpy.gui.data_bind import rgetattr, rsetattr, rhasattr
|
||||
from corrscope.gui.data_bind import rgetattr, rsetattr, rhasattr
|
||||
|
||||
|
||||
def test_rgetattr():
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import pytest
|
||||
|
||||
from ovgenpy.layout import LayoutConfig, RendererLayout
|
||||
from ovgenpy.renderer import RendererConfig, MatplotlibRenderer
|
||||
from corrscope.layout import LayoutConfig, RendererLayout
|
||||
from corrscope.renderer import RendererConfig, MatplotlibRenderer
|
||||
from tests.test_renderer import WIDTH, HEIGHT
|
||||
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ from typing import TYPE_CHECKING
|
|||
|
||||
import pytest
|
||||
|
||||
from ovgenpy.channel import ChannelConfig
|
||||
from ovgenpy.outputs import RGB_DEPTH, \
|
||||
from corrscope.channel import ChannelConfig
|
||||
from corrscope.outputs import RGB_DEPTH, \
|
||||
FFmpegOutput, FFmpegOutputConfig, FFplayOutput, FFplayOutputConfig
|
||||
from ovgenpy.ovgenpy import default_config, Ovgen, Arguments
|
||||
from ovgenpy.renderer import RendererConfig, MatplotlibRenderer
|
||||
from corrscope.corrscope import default_config, CorrScope, Arguments
|
||||
from corrscope.renderer import RendererConfig, MatplotlibRenderer
|
||||
from tests.test_renderer import WIDTH, HEIGHT, ALL_ZEROS
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -40,7 +40,7 @@ def test_output():
|
|||
assert not Path('-').exists()
|
||||
|
||||
|
||||
# Ensure ovgen closes pipe to output upon completion.
|
||||
# Ensure CorrScope closes pipe to output upon completion.
|
||||
@pytest.mark.usefixtures('Popen')
|
||||
def test_close_output(Popen):
|
||||
""" FFplayOutput unit test: Ensure ffmpeg and ffplay are terminated when Python
|
||||
|
@ -57,7 +57,7 @@ def test_close_output(Popen):
|
|||
popen.wait.assert_called() # Does wait() need to be called?
|
||||
|
||||
|
||||
# Ensure ovgen terminates FFplay upon exceptions.
|
||||
# Ensure CorrScope terminates FFplay upon exceptions.
|
||||
@pytest.mark.usefixtures('Popen')
|
||||
def test_terminate_ffplay(Popen):
|
||||
""" FFplayOutput unit test: Ensure ffmpeg and ffplay are terminated when Python
|
||||
|
@ -85,58 +85,58 @@ def sine440_config():
|
|||
|
||||
|
||||
@pytest.mark.usefixtures('Popen')
|
||||
def test_ovgen_terminate_ffplay(Popen, mocker: 'pytest_mock.MockFixture'):
|
||||
""" Integration test: Ensure ovgenpy calls terminate() on ffmpeg and ffplay when
|
||||
def test_corr_terminate_ffplay(Popen, mocker: 'pytest_mock.MockFixture'):
|
||||
""" Integration test: Ensure corrscope calls terminate() on ffmpeg and ffplay when
|
||||
Python exceptions occur. """
|
||||
|
||||
cfg = sine440_config()
|
||||
ovgen = Ovgen(cfg, Arguments('.', [FFplayOutputConfig()]))
|
||||
corr = CorrScope(cfg, Arguments('.', [FFplayOutputConfig()]))
|
||||
|
||||
render_frame = mocker.patch.object(MatplotlibRenderer, 'render_frame')
|
||||
render_frame.side_effect = DummyException()
|
||||
with pytest.raises(DummyException):
|
||||
ovgen.play()
|
||||
corr.play()
|
||||
|
||||
assert len(ovgen.outputs) == 1
|
||||
output: FFplayOutput = ovgen.outputs[0]
|
||||
assert len(corr.outputs) == 1
|
||||
output: FFplayOutput = corr.outputs[0]
|
||||
|
||||
for popen in output._pipeline:
|
||||
popen.terminate.assert_called()
|
||||
|
||||
|
||||
@pytest.mark.skip('Launches ffmpeg and ffplay processes, creating a ffplay window')
|
||||
def test_ovgen_terminate_works():
|
||||
def test_corr_terminate_works():
|
||||
""" Ensure that ffmpeg/ffplay terminate quickly after Python exceptions, when
|
||||
`popen.terminate()` is called. """
|
||||
|
||||
cfg = sine440_config()
|
||||
ovgen = Ovgen(cfg, Arguments('.', [FFplayOutputConfig()]))
|
||||
ovgen.raise_on_teardown = DummyException
|
||||
corr = CorrScope(cfg, Arguments('.', [FFplayOutputConfig()]))
|
||||
corr.raise_on_teardown = DummyException
|
||||
|
||||
with pytest.raises(DummyException):
|
||||
# Raises `subprocess.TimeoutExpired` if popen.terminate() doesn't work.
|
||||
ovgen.play()
|
||||
corr.play()
|
||||
|
||||
|
||||
# TODO test to ensure ffplay is killed before it terminates
|
||||
|
||||
def test_ovgen_output_without_audio():
|
||||
"""Ensure running ovgen with FFmpeg output, with master audio disabled,
|
||||
def test_corr_output_without_audio():
|
||||
"""Ensure running CorrScope with FFmpeg output, with master audio disabled,
|
||||
does not crash.
|
||||
"""
|
||||
cfg = sine440_config()
|
||||
cfg.master_audio = None
|
||||
|
||||
ovgen = Ovgen(cfg, Arguments('.', [NULL_OUTPUT]))
|
||||
corr = CorrScope(cfg, Arguments('.', [NULL_OUTPUT]))
|
||||
# Should not raise exception.
|
||||
ovgen.play()
|
||||
corr.play()
|
||||
|
||||
|
||||
def test_render_subfps_one():
|
||||
""" Ensure video gets rendered when render_subfps=1.
|
||||
This test fails if ceildiv is used to calculate `ahead`.
|
||||
"""
|
||||
from ovgenpy.outputs import IOutputConfig, Output, register_output
|
||||
from corrscope.outputs import IOutputConfig, Output, register_output
|
||||
|
||||
# region DummyOutput
|
||||
class DummyOutputConfig(IOutputConfig):
|
||||
|
@ -153,12 +153,12 @@ def test_render_subfps_one():
|
|||
assert DummyOutput
|
||||
# endregion
|
||||
|
||||
# Create Ovgen with render_subfps=1. Ensure multiple frames are outputted.
|
||||
# Create CorrScope with render_subfps=1. Ensure multiple frames are outputted.
|
||||
cfg = sine440_config()
|
||||
cfg.render_subfps = 1
|
||||
|
||||
ovgen = Ovgen(cfg, Arguments('.', [DummyOutputConfig()]))
|
||||
ovgen.play()
|
||||
corr = CorrScope(cfg, Arguments('.', [DummyOutputConfig()]))
|
||||
corr.play()
|
||||
assert DummyOutput.frames_written >= 2
|
||||
|
||||
|
||||
|
@ -177,17 +177,17 @@ def test_render_subfps_non_integer(mocker: 'pytest_mock.MockFixture'):
|
|||
assert cfg.render_fps != int(cfg.render_fps)
|
||||
assert Fraction(1) == int(1)
|
||||
|
||||
ovgen = Ovgen(cfg, Arguments('.', [NULL_OUTPUT]))
|
||||
ovgen.play()
|
||||
corr = CorrScope(cfg, Arguments('.', [NULL_OUTPUT]))
|
||||
corr.play()
|
||||
|
||||
# But it seems FFmpeg actually allows decimal -framerate (although a bad idea).
|
||||
# from ovgenpy.ovgenpy import Config
|
||||
# from corrscope.corrscope import Config
|
||||
# render_fps = mocker.patch.object(Config, 'render_fps',
|
||||
# new_callable=mocker.PropertyMock)
|
||||
# render_fps.return_value = 60 / 7
|
||||
# assert isinstance(cfg.render_fps, float)
|
||||
# ovgen = Ovgen(cfg, '.', outputs=[NULL_OUTPUT])
|
||||
# ovgen.play()
|
||||
# corr = CorrScope(cfg, '.', outputs=[NULL_OUTPUT])
|
||||
# corr.play()
|
||||
|
||||
|
||||
# Possibility: add a test to ensure that we render slightly ahead in time
|
||||
|
|
|
@ -2,10 +2,10 @@ import numpy as np
|
|||
import pytest
|
||||
from matplotlib.colors import to_rgb
|
||||
|
||||
from ovgenpy.channel import ChannelConfig
|
||||
from ovgenpy.outputs import RGB_DEPTH
|
||||
from ovgenpy.renderer import RendererConfig, MatplotlibRenderer
|
||||
from ovgenpy.layout import LayoutConfig
|
||||
from corrscope.channel import ChannelConfig
|
||||
from corrscope.outputs import RGB_DEPTH
|
||||
from corrscope.renderer import RendererConfig, MatplotlibRenderer
|
||||
from corrscope.layout import LayoutConfig
|
||||
|
||||
WIDTH = 640
|
||||
HEIGHT = 360
|
||||
|
|
|
@ -4,10 +4,10 @@ import pytest
|
|||
from matplotlib.axes import Axes
|
||||
from matplotlib.figure import Figure
|
||||
|
||||
from ovgenpy import triggers
|
||||
from ovgenpy.triggers import CorrelationTriggerConfig, CorrelationTrigger, \
|
||||
from corrscope import triggers
|
||||
from corrscope.triggers import CorrelationTriggerConfig, CorrelationTrigger, \
|
||||
PerFrameCache, ZeroCrossingTriggerConfig, LocalPostTriggerConfig
|
||||
from ovgenpy.wave import Wave
|
||||
from corrscope.wave import Wave
|
||||
|
||||
triggers.SHOW_TRIGGER = False
|
||||
|
||||
|
@ -179,7 +179,7 @@ def test_trigger_should_recalc_window():
|
|||
# Test the ability to load legacy TriggerConfig
|
||||
|
||||
def test_load_trigger_config():
|
||||
from ovgenpy.config import yaml
|
||||
from corrscope.config import yaml
|
||||
|
||||
# Ensure no exceptions
|
||||
yaml.load('''\
|
||||
|
|
|
@ -4,7 +4,7 @@ import numpy as np
|
|||
import pytest
|
||||
from delayed_assert import expect, assert_expectations
|
||||
|
||||
from ovgenpy.wave import Wave
|
||||
from corrscope.wave import Wave
|
||||
|
||||
prefix = 'tests/wav-formats/'
|
||||
wave_paths = [
|
||||
|
|
|
@ -2,7 +2,7 @@ import pytest
|
|||
import numpy as np
|
||||
from numpy.testing import assert_equal
|
||||
|
||||
from ovgenpy.utils.windows import leftpad, midpad
|
||||
from corrscope.utils.windows import leftpad, midpad
|
||||
|
||||
|
||||
def test_leftpad():
|
||||
|
|
Ładowanie…
Reference in New Issue