Merge pull request #12 from nqrduck/RX-dwelltime

Rx dwelltime
This commit is contained in:
Julia P 2024-05-05 15:46:49 +02:00 committed by GitHub
commit 03d5571b59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 67 additions and 12 deletions

View file

@ -1,5 +1,9 @@
# Changelog # Changelog
## Version 0.0.6 (05-05-2024)
- Added a dwell time setting for receiving. Additionally the sampling frequency is now settable. (`1a6342e4cb3ee5a351547dc389873f9ce8f20a15`)
- Measurements now have a name (`1bceba1a0f57ce168564cadecb30152020ca509c`)
### Version 0.0.5 (26-04-2024) ### Version 0.0.5 (26-04-2024)
- Added support for the new formbuilder provided by the nqrduck core - Added support for the new formbuilder provided by the nqrduck core

View file

@ -7,7 +7,7 @@ allow-direct-references = true
[project] [project]
name = "nqrduck-spectrometer-limenqr" name = "nqrduck-spectrometer-limenqr"
version = "0.0.5" version = "0.0.6"
authors = [ authors = [
{ name="jupfi", email="support@nqrduck.cool" }, { name="jupfi", email="support@nqrduck.cool" },
] ]

View file

@ -1,13 +1,16 @@
"""Controller module for the Lime NQR spectrometer.""" """Controller module for the Lime NQR spectrometer."""
import logging import logging
from datetime import datetime
import tempfile import tempfile
from pathlib import Path from pathlib import Path
import numpy as np import numpy as np
from scipy.signal import resample, decimate
from limedriver.binding import PyLimeConfig from limedriver.binding import PyLimeConfig
from limedriver.hdf_reader import HDF from limedriver.hdf_reader import HDF
from nqrduck.helpers.unitconverter import UnitConverter
from nqrduck_spectrometer.base_spectrometer_controller import BaseSpectrometerController from nqrduck_spectrometer.base_spectrometer_controller import BaseSpectrometerController
from nqrduck_spectrometer.measurement import Measurement from nqrduck_spectrometer.measurement import Measurement
from nqrduck_spectrometer.pulseparameters import TXPulse, RXReadout from nqrduck_spectrometer.pulseparameters import TXPulse, RXReadout
@ -55,6 +58,30 @@ class LimeNQRController(BaseSpectrometerController):
measurement_data = self.process_measurement_results(lime) measurement_data = self.process_measurement_results(lime)
# Resample the RX data to the dwell time settings
dwell_time = self.module.model.get_setting_by_name(
self.module.model.RX_DWELL_TIME
).value
dwell_time = UnitConverter.to_float(dwell_time) * 1e6
logger.debug("Dwell time: %s", dwell_time)
logger.debug(f"Last tdx value: {measurement_data.tdx[-1]}")
if dwell_time:
n_data_points = int(measurement_data.tdx[-1] / dwell_time)
logger.debug("Resampling to %s data points", n_data_points)
tdx = np.linspace(
0, measurement_data.tdx[-1], n_data_points, endpoint=False
)
tdy = resample(measurement_data.tdy, n_data_points)
name = measurement_data.name
measurement_data = Measurement(
name,
tdx,
tdy,
self.module.model.target_frequency,
IF_frequency=self.module.model.if_frequency,
)
if measurement_data: if measurement_data:
self.emit_measurement_data(measurement_data) self.emit_measurement_data(measurement_data)
self.emit_status_message("Finished Measurement") self.emit_status_message("Finished Measurement")
@ -168,7 +195,11 @@ class LimeNQRController(BaseSpectrometerController):
evidx = self.find_evaluation_range_indices(hdf, rx_begin, rx_stop) evidx = self.find_evaluation_range_indices(hdf, rx_begin, rx_stop)
tdx, tdy = self.extract_measurement_data(lime, hdf, evidx) tdx, tdy = self.extract_measurement_data(lime, hdf, evidx)
fft_shift = self.get_fft_shift() fft_shift = self.get_fft_shift()
# Measurement name date + module + target frequency + averages + sequence name
name = f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - LimeNQR - {self.module.model.target_frequency / 1e6} MHz - {self.module.model.averages} averages - {self.module.model.pulse_programmer.model.pulse_sequence.name}.quack"
logger.debug(f"Measurement name: {name}")
return Measurement( return Measurement(
name,
tdx, tdx,
tdy, tdy,
self.module.model.target_frequency, self.module.model.target_frequency,
@ -456,6 +487,7 @@ class LimeNQRController(BaseSpectrometerController):
parameter.get_option_by_name(TXPulse.RELATIVE_AMPLITUDE).value / 100 parameter.get_option_by_name(TXPulse.RELATIVE_AMPLITUDE).value / 100
) )
pulse_amplitude = np.clip(pulse_amplitude, -0.99, 0.99) pulse_amplitude = np.clip(pulse_amplitude, -0.99, 0.99)
return pulse_shape, pulse_amplitude return pulse_shape, pulse_amplitude
def modulate_pulse_amplitude( def modulate_pulse_amplitude(
@ -475,6 +507,11 @@ class LimeNQRController(BaseSpectrometerController):
num_samples = int(float(event.duration) * lime.srate) num_samples = int(float(event.duration) * lime.srate)
tdx = np.linspace(0, float(event.duration), num_samples, endpoint=False) tdx = np.linspace(0, float(event.duration), num_samples, endpoint=False)
shift_signal = np.exp(1j * 2 * np.pi * self.module.model.if_frequency * tdx) shift_signal = np.exp(1j * 2 * np.pi * self.module.model.if_frequency * tdx)
# The pulse amplitude needs to be resampled to the number of samples
logger.debug("Resampling pulse amplitude to %s samples", num_samples)
pulse_amplitude = resample(pulse_amplitude, num_samples)
pulse_complex = pulse_amplitude * shift_signal pulse_complex = pulse_amplitude * shift_signal
modulated_amplitude = np.abs(pulse_complex) modulated_amplitude = np.abs(pulse_complex)
modulated_phase = self.unwrap_phase(np.angle(pulse_complex)) modulated_phase = self.unwrap_phase(np.angle(pulse_complex))
@ -610,7 +647,7 @@ class LimeNQRController(BaseSpectrometerController):
result result
) # Reversed to maintain the original order if needed elsewhere ) # Reversed to maintain the original order if needed elsewhere
def translate_rx_event(self, lime : PyLimeConfig) -> tuple: def translate_rx_event(self, lime: PyLimeConfig) -> tuple:
"""This method translates the RX event of the pulse sequence to the limr object. """This method translates the RX event of the pulse sequence to the limr object.
Args: Args:
@ -671,7 +708,7 @@ class LimeNQRController(BaseSpectrometerController):
previous_events = events[: events.index(rx_event)] previous_events = events[: events.index(rx_event)]
return sum(event.duration for event in previous_events) return sum(event.duration for event in previous_events)
def calculate_offset(self, lime :PyLimeConfig) -> float: def calculate_offset(self, lime: PyLimeConfig) -> float:
"""This method calculates the offset for the RX event. """This method calculates the offset for the RX event.
Args: Args:

View file

@ -8,6 +8,7 @@ from nqrduck_spectrometer.settings import (
IntSetting, IntSetting,
BooleanSetting, BooleanSetting,
SelectionSetting, SelectionSetting,
StringSetting,
) )
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -19,17 +20,18 @@ class LimeNQRModel(BaseSpectrometerModel):
CHANNEL = "TX/RX Channel" CHANNEL = "TX/RX Channel"
TX_MATCHING = "TX Matching" TX_MATCHING = "TX Matching"
RX_MATCHING = "RX Matching" RX_MATCHING = "RX Matching"
SAMPLING_FREQUENCY = "Sampling Frequency" SAMPLING_FREQUENCY = "Sampling Frequency (Hz)"
IF_FREQUENCY = "IF Frequency" RX_DWELL_TIME = "RX Dwell Time (s)"
ACQUISITION_TIME = "Acquisition time" IF_FREQUENCY = "IF Frequency (Hz)"
ACQUISITION_TIME = "Acquisition time (s)"
GATE_ENABLE = "Enable" GATE_ENABLE = "Enable"
GATE_PADDING_LEFT = "Gate padding left" GATE_PADDING_LEFT = "Gate padding left"
GATE_PADDING_RIGHT = "Gate padding right" GATE_PADDING_RIGHT = "Gate padding right"
GATE_SHIFT = "Gate shift" GATE_SHIFT = "Gate shift"
RX_GAIN = "RX Gain" RX_GAIN = "RX Gain"
TX_GAIN = "TX Gain" TX_GAIN = "TX Gain"
RX_LPF_BW = "RX LPF BW" RX_LPF_BW = "RX LPF BW (Hz)"
TX_LPF_BW = "TX LPF BW" TX_LPF_BW = "TX LPF BW (Hz)"
TX_I_DC_CORRECTION = "TX I DC correction" TX_I_DC_CORRECTION = "TX I DC correction"
TX_Q_DC_CORRECTION = "TX Q DC correction" TX_Q_DC_CORRECTION = "TX Q DC correction"
TX_I_GAIN_CORRECTION = "TX I Gain correction" TX_I_GAIN_CORRECTION = "TX I Gain correction"
@ -79,15 +81,27 @@ class LimeNQRModel(BaseSpectrometerModel):
) )
self.add_setting(rx_matching_setting, self.ACQUISITION) self.add_setting(rx_matching_setting, self.ACQUISITION)
sampling_frequency_setting = FloatSetting(
sampling_frequency_options = [
"30.72e6",
"15.36e6",
"7.68e6",
]
sampling_frequency_setting = SelectionSetting(
self.SAMPLING_FREQUENCY, self.SAMPLING_FREQUENCY,
30.72e6, sampling_frequency_options,
"30.72e6",
"The rate at which the spectrometer samples the input signal.", "The rate at which the spectrometer samples the input signal.",
min_value=0,
max_value=30.72e6,
) )
self.add_setting(sampling_frequency_setting, self.ACQUISITION) self.add_setting(sampling_frequency_setting, self.ACQUISITION)
rx_dwell_time_setting = StringSetting(
self.RX_DWELL_TIME,
"22n",
"The time between samples in the receive path.",
)
self.add_setting(rx_dwell_time_setting, self.ACQUISITION)
if_frequency_setting = FloatSetting( if_frequency_setting = FloatSetting(
self.IF_FREQUENCY, self.IF_FREQUENCY,
5e6, 5e6,