frappy_psi.ultrasound: add input_delay and other improvments

Change-Id: I6cb5690d82d96d6775fcb649fc633c4039932463
This commit is contained in:
2025-03-19 15:29:17 +01:00
parent 7c60daa568
commit 8d62375483
3 changed files with 64 additions and 101 deletions

View File

@ -27,9 +27,9 @@ import numpy as np
from frappy_psi.adq_mr import Adq, PEdata, RUSdata
from frappy.core import Attached, BoolType, Done, FloatRange, HasIO, StatusType, \
IntRange, Module, Parameter, Readable, Writable, Drivable, StringIO, StringType, \
IDLE, BUSY, DISABLED, WARN, ERROR, TupleOf, ArrayOf, Command, Attached
IDLE, BUSY, DISABLED, WARN, ERROR, TupleOf, ArrayOf, Command, Attached, EnumType
from frappy.properties import Property
#from frappy.modules import Collector
# from frappy.modules import Collector
Collector = Readable
@ -95,8 +95,8 @@ class FreqStringIO(StringIO):
class Frequency(HasIO, Writable):
value = Parameter('frequency', unit='Hz')
amp = Parameter('amplitude', FloatRange(unit='dBm'), readonly=False)
amp = Parameter('amplitude (VPP)', FloatRange(unit='V'), readonly=False)
output = Parameter('output: L or R', EnumType(L=1, R=0), readonly=False, default='L')
last_change = 0
ioClass = FreqStringIO
dif = None
@ -115,14 +115,15 @@ class Frequency(HasIO, Writable):
self.last_change = time.time()
if self.dif:
self.dif.read_value()
self.read_value()
return self._freq
def write_amp(self, amp):
reply = self.communicate('AMPR %g;AMPR?' % amp)
reply = self.communicate(f'AMP{self.output.name} {amp} VPP;AMP{self.output.name}? VPP')
return float(reply)
def read_amp(self):
reply = self.communicate('AMPR?')
reply = self.communicate(f'AMP{self.output.name}? VPP')
return float(reply)
@ -146,9 +147,7 @@ class Base:
def shutdownModule(self):
if self.adq:
print('shutdownModule')
self.adq.deletecu()
print('shutdoneModule done')
self.adq = None
@ -236,11 +235,17 @@ class RUS(Base, Collector):
freq = Attached()
imod = Attached(mandatory=False)
qmod = Attached(mandatory=False)
input_signal = Attached(mandatory=False)
output_signal = Attached(mandatory=False)
value = Parameter('averaged (I, Q) tuple', TupleOf(FloatRange(), FloatRange()))
status = Parameter(datatype=StatusType(Readable, 'BUSY'))
periods = Parameter('number of periods', IntRange(1, 9999), default=12)
input_range = Parameter('input range (taking in to account attenuation)', FloatRange(unit='V'), default=0.1, readonly=False)
output_range = Parameter('output range', FloatRange(unit='V'), default=0.1, readonly=False)
input_delay = Parameter('throw away everything before this time',
FloatRange(unit='ns'), default=10000, readonly=False)
input_range = Parameter('input range (taking in to account attenuation)', FloatRange(unit='V'),
default=10, readonly=False)
output_range = Parameter('output range', FloatRange(unit='V'),
default=1, readonly=False)
input_phase_stddev = Parameter('input signal quality', FloatRange(unit='rad'), default=0)
output_phase_slope = Parameter('output signal phase slope', FloatRange(unit='rad/sec'), default=0)
output_amp_slope = Parameter('output signal amplitude change', FloatRange(unit='1/sec'), default=0)
@ -249,7 +254,7 @@ class RUS(Base, Collector):
phase = Parameter('phase', FloatRange(unit='deg'), default=0)
amp = Parameter('amplitude', FloatRange(), default=0)
continuous = Parameter('continuous mode', BoolType(), readonly=False, default=True)
pollinterval = Parameter(default=1)
pollinterval = Parameter(datatype=FloatRange(0, 120), default=1)
_starttime = None
_iq = 0
@ -262,8 +267,12 @@ class RUS(Base, Collector):
super().initModule()
self.adq = Adq()
self._ovr_rate = {}
self.freq.addCallback('value', self.update_freq)
# self.write_periods(self.periods)
def update_freq(self, value):
self.setFastPoll(True, 0.001)
def doPoll(self):
try:
data = self.adq.get_data()
@ -283,11 +292,15 @@ class RUS(Base, Collector):
else:
self._ovr_rate.pop(chan.name, None)
qual = data.get_quality()
if self.input_signal:
self.input_signal.value = np.round(data.channels[0].binned, 3)
if self.output_signal:
self.output_signal.value = np.round(data.channels[1].binned, 3)
self.input_phase_stddev = qual.input_stddev.imag
self.output_phase_slope = qual.output_slope.imag
self.output_amp_slope = qual.output_slope.real
self.input_amplitude = data.inp.amplitude / 2 ** 15 * self.input_range
self.output_amplitude = data.out.amplitude / 2 ** 15 * self.output_range
self.input_amplitude = data.inp.amplitude * self.input_range
self.output_amplitude = data.out.amplitude * self.output_range
self._iq = iq = data.iq * self.output_range / self.input_range
self.phase = np.arctan2(iq.imag, iq.real) * 180 / np.pi
self.amp = np.abs(iq)
@ -351,12 +364,17 @@ class RUS(Base, Collector):
def start_acquisition(self):
freq = self.freq.read_value()
self.sr = round(self.periods * self.adq.sample_rate / freq)
self.adq.init(self.sr, 1)
self.adq.start(RUSdata(self.adq, freq, self.periods))
delay_samples = round(self.input_delay * self.adq.sample_rate * 1e-9)
self.adq.init(self.sr + delay_samples, 1)
self.adq.start(RUSdata(self.adq, freq, self.periods, delay_samples))
self._busy = True
self.setFastPoll(True, 0.001)
class Signal(Readable):
value = Parameter('pulse', ArrayOf(FloatRange(), maxlen=9999))
class ControlLoop(Module):
roi = Attached(Roi)
maxstep = Parameter('max frequency step', FloatRange(unit='Hz'), readonly=False,