94 lines
3.5 KiB
Python
94 lines
3.5 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)
|