90 lines
3.1 KiB
Python
90 lines
3.1 KiB
Python
"""Presentation state for waveform rulers; no transport or wire processing."""
|
|
from dataclasses import dataclass
|
|
|
|
|
|
def drag_zoom_factor(delta_pixels):
|
|
"""Visual gesture mapping: 200 pixels doubles the selected axis."""
|
|
return 2 ** (max(-1000., min(1000., delta_pixels)) / 200.)
|
|
|
|
|
|
@dataclass
|
|
class Marker:
|
|
name: str
|
|
axis: str
|
|
value: float
|
|
color: str
|
|
visible: bool = False
|
|
|
|
|
|
class WaveformMarkers:
|
|
def __init__(self):
|
|
self.items = [Marker('X1', 'x', .2, '#ffce63'),
|
|
Marker('X2', 'x', .4, '#ffce63'),
|
|
Marker('X3', 'x', .6, '#e794ff'),
|
|
Marker('X4', 'x', .8, '#e794ff'),
|
|
Marker('Y1', 'y', .2, '#72e7ff'),
|
|
Marker('Y2', 'y', .4, '#72e7ff'),
|
|
Marker('Y3', 'y', .6, '#a9df79'),
|
|
Marker('Y4', 'y', .8, '#a9df79')]
|
|
self._math = None
|
|
self.session = None
|
|
self.bounds = None
|
|
|
|
def window(self, session, start, end):
|
|
if session != self.session or self.bounds is None:
|
|
for marker, fraction in zip(self.items[:4], (.2, .4, .6, .8)):
|
|
marker.value = start + (end-start)*fraction
|
|
self.session, self.bounds = session, (start, end)
|
|
|
|
def reset(self):
|
|
if self.bounds:
|
|
start, end = self.bounds
|
|
for marker, fraction in zip(self.items[:4], (.2, .4, .6, .8)):
|
|
marker.value = start + (end-start)*fraction
|
|
for marker, fraction in zip(self.items[4:], (.2, .4, .6, .8)):
|
|
marker.value = fraction
|
|
|
|
def measurements(self, period_ns):
|
|
"""Use the same native delta operation as Android's plotDelta."""
|
|
if self._math is None:
|
|
from protocan.plot import PlotMath
|
|
from .native import NativeAnalyzer
|
|
self._math = PlotMath(NativeAnalyzer().lib)
|
|
result = []
|
|
for index in range(0, 8, 2):
|
|
a, b = self.items[index:index+2]
|
|
if not (a.visible and b.visible):
|
|
continue
|
|
if a.axis == 'x':
|
|
if self.bounds is None:
|
|
continue
|
|
factor = period_ns / 1e9
|
|
av, bv = a.value*factor, b.value*factor
|
|
delta = self._math.delta(a.value, b.value, factor)
|
|
frequency = 1/abs(delta) if delta else None
|
|
else:
|
|
av, bv = 100*(1-a.value), 100*(1-b.value)
|
|
delta = self._math.delta(av, bv)
|
|
frequency = None
|
|
result.append((a, b, av, bv, delta, frequency))
|
|
return result
|
|
|
|
def place(self, index, fraction):
|
|
marker = self.items[index]
|
|
fraction = min(1., max(0., fraction))
|
|
if marker.axis == 'x':
|
|
if self.bounds is None:
|
|
return
|
|
start, end = self.bounds
|
|
marker.value = start + (end-start)*fraction
|
|
else:
|
|
marker.value = fraction
|
|
|
|
def fraction(self, marker):
|
|
if marker.axis == 'y':
|
|
return marker.value
|
|
if self.bounds is None:
|
|
return 0.
|
|
start, end = self.bounds
|
|
return (marker.value-start)/max(1, end-start)
|