mirror of
https://github.com/nqrduck/nqrduck-spectrometer-limenqr.git
synced 2024-12-22 23:47:47 +00:00
commit
03d5571b59
4 changed files with 67 additions and 12 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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" },
|
||||||
]
|
]
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue