This commit is contained in:
jupfi 2024-06-24 18:09:46 +02:00
parent c72be61c0f
commit 1fceff04d7
4 changed files with 36 additions and 17 deletions

View file

@ -232,9 +232,15 @@ class FunctionOption(Option):
obj = cls(data["name"], functions) obj = cls(data["name"], functions)
obj.value = Function.from_json(data["value"]) obj.value = Function.from_json(data["value"])
return obj return obj
class TableOption(Option): class TableOption(Option):
"""A table option has rows and columns and can be used to store a table of values. The value is a list of lists.""" """A table option has rows and columns and can be used to store a table of values.
The table option acts as a 'meta' option, which means that we can add different types of options to the table as rows.
Associated with every row we can add a number of different values.
The number of rows can be adjusted at runtime.
"""
def __init__(self, name: str, value) -> None: def __init__(self, name: str, value) -> None:
"""Initializes the table option.""" """Initializes the table option."""

View file

@ -1,3 +1,5 @@
"""The phase table module contains the PhaseTable class, which interprets the TX parameters of a QuackSequence object and then generates a table of different phase values and signs for each phasecycle."""
import logging import logging
import numpy as np import numpy as np
from collections import OrderedDict from collections import OrderedDict
@ -11,6 +13,7 @@ class PhaseTable:
"""A phase table interprets the TX parameters of a QuackSequence object and then generates a table of different phase values and signs for each phasecycle.""" """A phase table interprets the TX parameters of a QuackSequence object and then generates a table of different phase values and signs for each phasecycle."""
def __init__(self, quackseq): def __init__(self, quackseq):
"""Initializes the phase table."""
self.quackseq = quackseq self.quackseq = quackseq
self.phase_array = self.generate_phase_array() self.phase_array = self.generate_phase_array()
@ -21,7 +24,6 @@ class PhaseTable:
phase_array (np.array): A table of phase values for each phasecycle. phase_array (np.array): A table of phase values for each phasecycle.
The columns are the values for the different TX pulse parameters and the rows are the different phase cycles. The columns are the values for the different TX pulse parameters and the rows are the different phase cycles.
""" """
phase_table = OrderedDict() phase_table = OrderedDict()
events = self.quackseq.events events = self.quackseq.events
@ -63,7 +65,9 @@ class PhaseTable:
logger.info(phase_table) logger.info(phase_table)
# Now get the maximum phase group # Now get the maximum phase group
max_phase_group = int(max([phase_group for phase_group, _ in phase_table.values()])) max_phase_group = int(
max([phase_group for phase_group, _ in phase_table.values()])
)
logger.info(f"Max phase group: {max_phase_group}") logger.info(f"Max phase group: {max_phase_group}")
@ -79,7 +83,7 @@ class PhaseTable:
for parameter, (group, phase_values) in phase_table.items(): for parameter, (group, phase_values) in phase_table.items():
if max_phase_values < len(phase_values): if max_phase_values < len(phase_values):
max_phase_values = len(phase_values) max_phase_values = len(phase_values)
n_rows *= max_phase_values n_rows *= max_phase_values
max_phase_values = 1 max_phase_values = 1
@ -155,7 +159,9 @@ class PhaseTable:
try: try:
total_group_phases[i] += [parameter, phases[i]] total_group_phases[i] += [parameter, phases[i]]
except IndexError: except IndexError:
logger.info(f"Index Error 1: Parameter {parameter}, Phases: {phases}") logger.info(
f"Index Error 1: Parameter {parameter}, Phases: {phases}"
)
return total_group_phases return total_group_phases
@ -170,12 +176,14 @@ class PhaseTable:
try: try:
phase_array[row, column] = phase_value phase_array[row, column] = phase_value
except IndexError as e: except IndexError as e:
logger.info(f"Index error 2: {row}, {column}, {phase_value}, {phase}, {e}") logger.info(
f"Index error 2: {row}, {column}, {phase_value}, {phase}, {e}"
)
logger.info(phase_array) logger.info(phase_array)
return phase_array return phase_array
def update_phase_array(self): def update_phase_array(self):
"""Update the phase array of the sequence.""" """Update the phase array of the sequence."""
self.phase_array = self.generate_phase_array() self.phase_array = self.generate_phase_array()
@ -184,15 +192,17 @@ class PhaseTable:
def phase_array(self) -> np.array: def phase_array(self) -> np.array:
"""The phase array of the sequence.""" """The phase array of the sequence."""
return self._phase_array return self._phase_array
@phase_array.setter @phase_array.setter
def phase_array(self, phase_array : np.array): def phase_array(self, phase_array: np.array):
self._phase_array = phase_array self._phase_array = phase_array
@property @property
def n_phase_cycles(self) -> int: def n_phase_cycles(self) -> int:
"""The number of phase cycles in the sequence."""
return self.phase_array.shape[0] return self.phase_array.shape[0]
@property @property
def n_parameters(self) -> int: def n_parameters(self) -> int:
"""The number of TX pulse parameters in the sequence."""
return self.phase_array.shape[1] return self.phase_array.shape[1]

View file

@ -2,7 +2,7 @@
This example demonstrates how to simulate a composite FID signal using the quackseq simulator. This example demonstrates how to simulate a composite FID signal using the quackseq simulator.
See the paper: See the paper:
Sauer, K.L., Klug, C.A., Miller, J.B. et al. Using quaternions to design composite pulses for spin-1 NQR. Appl. Magn. Reson. 25, 485500 (2004). https://doi.org/10.1007/BF03166543 Sauer, K.L., Klug, C.A., Miller, J.B. et al. Using quaternions to design composite pulses for spin-1 NQR. Appl. Magn. Reson. 25, 485500 (2004). https://doi.org/10.1007/BF03166543
This also works for Samples with spin > 1. This also works for Samples with spin > 1.
@ -11,15 +11,16 @@ This also works for Samples with spin > 1.
from quackseq.pulsesequence import QuackSequence from quackseq.pulsesequence import QuackSequence
from quackseq.functions import RectFunction from quackseq.functions import RectFunction
def create_COMPFID():
def create_COMPFID():
"""Creates a composite FID sequence."""
COMPFID = QuackSequence("COMPFID") COMPFID = QuackSequence("COMPFID")
COMPFID.add_pulse_event("tx1", "3u", 100, 0, RectFunction()) COMPFID.add_pulse_event("tx1", "3u", 100, 0, RectFunction())
COMPFID.add_pulse_event("tx2", "6u", 100, 45, RectFunction()) COMPFID.add_pulse_event("tx2", "6u", 100, 45, RectFunction())
# This makes the phase 45, 135, 225, 315 (because of the previous 45 degree phase shift and 360/4 = 90 degree phase shift) # This makes the phase 45, 135, 225, 315 (because of the previous 45 degree phase shift and 360/4 = 90 degree phase shift)
COMPFID.set_tx_n_phase_cycles("tx2", 4) COMPFID.set_tx_n_phase_cycles("tx2", 4)
COMPFID.add_blank_event("blank", "5u") COMPFID.add_blank_event("blank", "5u")
COMPFID.add_readout_event("rx", "100u") COMPFID.add_readout_event("rx", "100u")
# No phase shifiting of the receive data but weighting of -1 for the 45 degree pulse, +1 for the 135 degree pulse, -1 for the 225 degree pulse and +1 for the 315 degree pulse # No phase shifiting of the receive data but weighting of -1 for the 45 degree pulse, +1 for the 135 degree pulse, -1 for the 225 degree pulse and +1 for the 315 degree pulse
@ -27,4 +28,4 @@ def create_COMPFID():
COMPFID.set_rx_readout_scheme("rx", readout_scheme) COMPFID.set_rx_readout_scheme("rx", readout_scheme)
return COMPFID return COMPFID

View file

@ -3,13 +3,15 @@
from quackseq.pulsesequence import QuackSequence from quackseq.pulsesequence import QuackSequence
from quackseq.functions import RectFunction from quackseq.functions import RectFunction
def create_SEPC() -> QuackSequence: def create_SEPC() -> QuackSequence:
"""Creates a simple spin echo sequence with phase cycling. """Creates a simple spin echo sequence with phase cycling.
The sequence consists of a pi/2 pulse, a pi pulse, and a readout event. The sequence consists of a pi/2 pulse, a pi pulse, and a readout event.
The phase cycling is set to cycle through 0°, 90°, 180°, 270° for the first pulse and constant 180° for the second pulse. The phase cycling is set to cycle through 0°, 90°, 180°, 270° for the first pulse and constant 180° for the second pulse.
The readout phase for the different phase cycles is set to 0°, 90°, 180°, 270°. The readout phase for the different phase cycles is set to 0°, 90°, 180°, 270°.
Returns: Returns:
QuackSequence: The SEPC sequence QuackSequence: The SEPC sequence
""" """
@ -29,4 +31,4 @@ def create_SEPC() -> QuackSequence:
sepc.set_rx_readout_scheme("rx", readout_scheme) sepc.set_rx_readout_scheme("rx", readout_scheme)
return sepc return sepc