Skip to content

Commit

Permalink
Merge pull request #12 from nqrduck/RX-dwelltime
Browse files Browse the repository at this point in the history
Rx dwelltime
  • Loading branch information
jupfi committed May 5, 2024
2 parents 2c63fa4 + e9ba962 commit 03d5571
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 12 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# 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)
- Added support for the new formbuilder provided by the nqrduck core

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ allow-direct-references = true

[project]
name = "nqrduck-spectrometer-limenqr"
version = "0.0.5"
version = "0.0.6"
authors = [
{ name="jupfi", email="support@nqrduck.cool" },
]
Expand Down
41 changes: 39 additions & 2 deletions src/nqrduck_spectrometer_limenqr/controller.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
"""Controller module for the Lime NQR spectrometer."""

import logging
from datetime import datetime
import tempfile
from pathlib import Path
import numpy as np
from scipy.signal import resample, decimate

from limedriver.binding import PyLimeConfig
from limedriver.hdf_reader import HDF

from nqrduck.helpers.unitconverter import UnitConverter
from nqrduck_spectrometer.base_spectrometer_controller import BaseSpectrometerController
from nqrduck_spectrometer.measurement import Measurement
from nqrduck_spectrometer.pulseparameters import TXPulse, RXReadout
Expand Down Expand Up @@ -55,6 +58,30 @@ def start_measurement(self):

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:
self.emit_measurement_data(measurement_data)
self.emit_status_message("Finished Measurement")
Expand Down Expand Up @@ -168,7 +195,11 @@ def calculate_measurement_data(
evidx = self.find_evaluation_range_indices(hdf, rx_begin, rx_stop)
tdx, tdy = self.extract_measurement_data(lime, hdf, evidx)
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(
name,
tdx,
tdy,
self.module.model.target_frequency,
Expand Down Expand Up @@ -456,6 +487,7 @@ def prepare_pulse_amplitude(self, event, parameter):
parameter.get_option_by_name(TXPulse.RELATIVE_AMPLITUDE).value / 100
)
pulse_amplitude = np.clip(pulse_amplitude, -0.99, 0.99)

return pulse_shape, pulse_amplitude

def modulate_pulse_amplitude(
Expand All @@ -475,6 +507,11 @@ def modulate_pulse_amplitude(
num_samples = int(float(event.duration) * lime.srate)
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)

# 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
modulated_amplitude = np.abs(pulse_complex)
modulated_phase = self.unwrap_phase(np.angle(pulse_complex))
Expand Down Expand Up @@ -610,7 +647,7 @@ def get_previous_events_without_tx_pulse(self, events, current_event) -> list:
result
) # 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.
Args:
Expand Down Expand Up @@ -671,7 +708,7 @@ def calculate_previous_events_duration(self, events, rx_event):
previous_events = events[: events.index(rx_event)]
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.
Args:
Expand Down
32 changes: 23 additions & 9 deletions src/nqrduck_spectrometer_limenqr/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
IntSetting,
BooleanSetting,
SelectionSetting,
StringSetting,
)

logger = logging.getLogger(__name__)
Expand All @@ -19,17 +20,18 @@ class LimeNQRModel(BaseSpectrometerModel):
CHANNEL = "TX/RX Channel"
TX_MATCHING = "TX Matching"
RX_MATCHING = "RX Matching"
SAMPLING_FREQUENCY = "Sampling Frequency"
IF_FREQUENCY = "IF Frequency"
ACQUISITION_TIME = "Acquisition time"
SAMPLING_FREQUENCY = "Sampling Frequency (Hz)"
RX_DWELL_TIME = "RX Dwell Time (s)"
IF_FREQUENCY = "IF Frequency (Hz)"
ACQUISITION_TIME = "Acquisition time (s)"
GATE_ENABLE = "Enable"
GATE_PADDING_LEFT = "Gate padding left"
GATE_PADDING_RIGHT = "Gate padding right"
GATE_SHIFT = "Gate shift"
RX_GAIN = "RX Gain"
TX_GAIN = "TX Gain"
RX_LPF_BW = "RX LPF BW"
TX_LPF_BW = "TX LPF BW"
RX_LPF_BW = "RX LPF BW (Hz)"
TX_LPF_BW = "TX LPF BW (Hz)"
TX_I_DC_CORRECTION = "TX I DC correction"
TX_Q_DC_CORRECTION = "TX Q DC correction"
TX_I_GAIN_CORRECTION = "TX I Gain correction"
Expand Down Expand Up @@ -79,15 +81,27 @@ def __init__(self, module) -> None:
)
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,
30.72e6,
sampling_frequency_options,
"30.72e6",
"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)

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(
self.IF_FREQUENCY,
5e6,
Expand Down

0 comments on commit 03d5571

Please sign in to comment.