2. T2 Measurement#
The following example shows how to perform a T2 measurement and fit the T2 decay to get the T2 value. The example can essentially be broken down as follows:
- Create an - AcquisitionControlusing the default device configuration from the repository. Here we can also set the log level for the log-file and the console log-output.
- Construct the T2 relaxation sequence. The range of echo times used for the measurement is given as a tuple. The number of experiments in between is defined by - num_steps. The repetition time (TR) between each spin-echo experiments can also be specified. Note that this sequence constructor also returns a list of TE values used in the experiment.
- Define - AcquisitionParameter, namely Larmor frequency \(f_0\), b1 scaling factor and the DDC decimation factor.
- Execute the experiment and extract the raw data. The data for the different TE values is stored in the phase encoding dimension. E.g. if - num_steps = 50, the second last dimension of the raw data should be 50.
- Extract the maximum of the complex signal in time domain for each echo time. 
- Define the T2 model given by \(A + B e^{- \frac{\text{TE}}{C}}\) and fit the determined maximum values using the TE values from the sequence. 
- The fitted parameters are used to calculate the decay for a larger echo-time-space and the result is plotted along with the measured data points. 
- Add some note to the meta data of the - AcquisitionDataand save the results using the- writemethod.
- Delete the acquisition control. This is an important step, as the destructor - __del__of the- AcquisitionControlclass disconnects from the measurement cards.
"""Spin-echo spectrum."""
# %%
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
import console
from console.interfaces.acquisition_data import AcquisitionData
from console.spcm_control.acquisition_control import AcquisitionControl
from console.utilities import sequences
# Create acquisition control instance
acq = AcquisitionControl(configuration_file="example_device_config.yaml")
# Construct and plot sequence
params = {
    "echo_time_range": (10e-3, 100e-3),
    "num_steps": 50,
    "repetition_time": 600e-3,
}
seq, te_values = sequences.t2_relaxation.constructor(**params)
# Set larmor frequency and b1 scaling factor
console.parameter.larmor_frequency = 2038550.0
console.parameter.b1_scaling = 2.43
# Perform acquisition
acq.set_sequence(sequence=seq, parameter=console.parameter)
acq_data: AcquisitionData = acq.run()
num_avg = acq_data.receive_data[0].total_averages
num_echos = int(len(acq_data.receive_data) / num_avg)
num_coils = np.size(acq_data.receive_data[0].processed_data, 0)
num_points = np.size(acq_data.receive_data[0].processed_data, 1)
data = np.zeros((num_avg, num_coils, num_echos, num_points), dtype=complex)
for idx, echo in enumerate(acq_data.receive_data):
    data[echo.average_index, :, idx % num_echos, :] = echo.processed_data
data = np.mean(data, axis=0).squeeze()
peaks = np.max(data, axis=-1)
# T2 model to fit the acquired data
def t2_model(te_values, a, b, c) -> np.ndarray:
    """Model for T2 relaxation."""
    return a + b * np.exp(-te_values / c)
# Fit parameters to measured data
params = curve_fit(t2_model, xdata=te_values, ydata=np.abs(peaks))[0]
t2 = params[-1]
te_values_fit = np.linspace(te_values[0], te_values[-1], 1000)
# Calculate decay with fitted parameters
t2_fit = t2_model(te_values_fit, *params)
# Plot measurement and fit
fig, ax = plt.subplots(1, 1, figsize=(10, 6))
ax.scatter(te_values * 1e3, np.abs(peaks), marker="x", c="b", label="Measurement")
ax.set_xlabel("TE [ms]")
ax.set_ylabel("Abs. signal ampliude [mV]")
ax.plot(te_values_fit * 1e3, t2_fit, linestyle="--", c="r", label=f"Fit, T2 = {round(t2 * 1e3, 4)} ms")
ax.legend()
# Save
# Add information to acquisition data
acq_data.add_info({
    "preamp": "china_preamp",
    "te_values": list(te_values),
    "T2_ms": t2,
})
acq_data.save()
del acq
# %%
 
    