Started pulse sequence translation.

This commit is contained in:
jupfi 2023-07-13 15:58:12 +02:00
parent c4b70065e0
commit ecd779ed1f
4 changed files with 129 additions and 53 deletions

6
.gitignore vendored
View file

@ -19,4 +19,8 @@ build/
venv/
# Other
*.DS_Store
*.DS_Store
# Contrib files without permission
src/nqrduck_spectrometer_limenqr/contrib/limr.py
src/nqrduck_spectrometer_limenqr/contrib/pulseN_test_USB.cpp

View file

@ -1,4 +1,6 @@
import logging
from pathlib import Path
import numpy as np
from nqrduck.module.module_controller import ModuleController
from nqrduck_spectrometer.base_spectrometer_controller import BaseSpectrometerController
@ -10,3 +12,90 @@ class LimeNQRController(BaseSpectrometerController):
def start_measurement(self):
logger.debug("Starting measurement with spectrometer: %s", self.module.model.name)
# Now we request the pulse sequence set in the pulse programmer module
pulse_sequence = self.module.model.pulse_programmer.model.pulse_sequence
logger.debug("Pulse sequence is: %s", pulse_sequence.dump_sequence_data())
try:
from .contrib.limr import limr
self_path = Path(__file__).parent
driver_path = str(self_path / "contrib/pulseN_test_USB.cpp")
lime = limr(driver_path)
except ImportError as e:
logger.error("Error while importing limr. %s", e)
except Exception as e:
logger.error("Error while loading pulseN_test_USB.cpp: %s", e)
lime = self.update_settings(lime)
lime = self.translate_pulse_sequence(lime)
def update_settings(self, lime):
logger.debug("Updating settings for spectrometer: %s for measurement", self.module.model.name)
l.t3d = [0, 0, 0, 0]
for category in self.module.model.settings.keys():
for setting in self.module.model.settings[category]:
logger.debug("Setting %s has value %s", setting.name, setting.value)
if setting.name == "RX Gain":
lime.rgn = setting.value
elif setting.name == "TX Gain":
lime.tgn = setting.value
elif setting.name == "Averages":
lime.nav = setting.value
elif setting.name == "Sampling Frequency":
lime.sra = setting.value
elif setting.name == "RX LPF BW":
lime.rlp = setting.value
elif setting.name == "TX LPF BW":
lime.tlp = setting.value
elif setting.name == "IF frequency":
lime.lof = self.target_frequency - setting.value
elif setting.name == "Acquisition time":
lime.tac = 82e-6
elif setting.name == "Enable":
lime.t3d[0] = int(setting.value)
elif setting.name == "Gate padding left":
lime.t3d[1] = setting.value
elif setting.name == "Gate shift":
lime.t3d[2] = setting.value
elif setting.name == "Gate padding right":
lime.t3d[3] = setting.value
return lime
def translate_pulse_sequence(self, lime):
"""This method translates the pulse sequence into the format required by the lime spectrometer.
"""
for event in self.module.model.pulse_programmer.model.pulse_sequence.events.values():
logger.debug("Event %s has parameters: %s", event.name, event.parameters)
for parameter in event.parameters.values():
logger.debug("Parameter %s has options: %s", parameter.name, parameter.options)
if parameter.name == "TX":
if len(lime.pfr) == 0:
# Add the TX pulse to the pulse frequency list (lime.pfr)
lime.pfr = [self.module.model.if_frequency]
# Add the duration of the TX pulse to the pulse duration list (lime.pdr)
lime.pdr = [event.duration]
# Add the TX pulse amplitude to the pulse amplitude list (lime.pam)
lime.pam = [parameter.options["TX Amplitude"].value]
# Add the pulse offset to the pulse offset list (lime.pof)
# This leads to a default offset of 300 samples for the first pulse
lime.pof = [300]
# Add the TX pulse phase to the pulse phase list (lime.pph) -> not yet implemented
else:
lime.pfr.append(self.module.model.if_frequency)
lime.pdr.append(event.duration)
lime.pam.append(parameter.options["TX Amplitude"].value)
lime.pof.append(np.ceil(lime.pfr[-2] * lime.sra))
# The acquisition time can be calculated from the buffer length of 4096 samples and the sampling frequency
# 82µs is the shortest possible acquisition time
# The last event is the repetition time event
lime.trp = event.duration
lime.npu = len(lime.pfr)
return lime

View file

@ -10,18 +10,42 @@ class LimeNQRModel(BaseSpectrometerModel):
def __init__(self, module) -> None:
super().__init__(module)
self.add_setting("Frequency", 100, "Experiment frequency", "Acquisition")
# Acquisition settings
self.add_setting("Frequency", 100e6, "Experiment frequency", "Acquisition")
self.target_frequency = 100e6
self.add_setting("Averages", 100, "Number of averages", "Acquisition")
self.add_setting("Sampling Frequency", 30.72e6 , "Sampling frequency", "Acquisition")
self.add_setting("IF Frequency", 1.2e6, "IF frequency", "Acquisition")
self.if_frequency = 1.2e6
self.add_setting("Acquisition time", 82e-6, "Acquisition time - this is from the beginning of the pulse sequence", "Acquisition")
# Gate Settings
self.add_setting("Enable", True, "Enable", "Gate Settings")
self.add_setting("Gate padding left", 10, "Gate padding left", "Gate Settings")
self.add_setting("Gate padding right", 10, "Gate padding right", "Gate Settings")
self.add_setting("Gate shift", 53, "Gate shift", "Gate Settings")
# RX/TX settings
self.add_setting("RX Gain", 55, "RX Gain", "RX/TX Settings")
self.add_setting("TX Gain", 40, "TX Gain", "RX/TX Settings")
self.add_setting("RX LPF BW", 30.72e6/2, "RX LPF BW", "RX/TX Settings")
self.add_setting("TX LPF BW", 130.0e6, "TX LPF BW", "RX/TX Settings")
# Calibration settings
self.add_setting("TX I DC correction", -45, "TX I DC correction", "Calibration")
self.add_setting("TX Q DC correction", 0, "TX Q DC correction", "Calibration")
self.add_setting("TX I Gain correction", 2047, "TX I Gain correction", "Calibration")
self.add_setting("TX Q Gain correction", 2039, "TX Q Gain correction", "Calibration")
self.add_setting("TX phase adjustment", 3, "TX phase adjustment", "Calibration")
self.add_setting("RX I DC correction", 0, "TX I DC correction", "Calibration")
self.add_setting("RX Q DC correction", 0, "TX Q DC correction", "Calibration")
self.add_setting("RX I Gain correction", 2047, "TX I Gain correction", "Calibration")
self.add_setting("RX Q Gain correction", 2047, "TX Q Gain correction", "Calibration")
self.add_setting("RX phase adjustment", 0, "TX phase adjustment", "Calibration")
# Pulse parameter options
self.add_pulse_parameter_option("TX", TXPulse)
self.add_pulse_parameter_option("Gate", Gate)
self.add_pulse_parameter_option("RX", RXReadout)
# Try to load the pulse programmer module
try:
from nqrduck_pulseprogrammer.pulseprogrammer import pulse_programmer
self.pulse_programmer = pulse_programmer
@ -31,60 +55,19 @@ class LimeNQRModel(BaseSpectrometerModel):
logger.warning("No pulse programmer found.")
@property
def rx_antenna(self):
return self._rx_antenna
def target_frequency(self):
return self._target_frequency
@rx_antenna.setter
def rx_antenna(self, value):
self._rx_antenna = value
@target_frequency.setter
def target_frequency(self, value):
self._target_frequency = value
@property
def tx_antenna(self):
return self._tx_antenna
def if_frequency(self):
return self._if_frequency
@tx_antenna.setter
def tx_antenna(self, value):
self._tx_antenna = value
@if_frequency.setter
def if_frequency(self, value):
self._if_frequency = value
@property
def rx_gain(self):
return self._rx_gain
@rx_gain.setter
def rx_gain(self, value):
self._rx_gain = value
@property
def tx_gain(self):
return self._tx_gain
@tx_gain.setter
def tx_gain(self, value):
self._tx_gain = value
@property
def rx_lpfbw(self):
return self._rx_lpfbw
@rx_lpfbw.setter
def rx_lpfbw(self, value):
self._rx_lpfbw = value
@property
def tx_lpfbw(self):
return self._tx_lpfbw
@tx_lpfbw.setter
def tx_lpfbw(self, value):
self._tx_lpfbw = value
# Pulse params
@property
def tx_freq(self):
return self._tx_freq
@tx_freq.setter
def tx_freq(self, value):
self._tx_freq = value