Signal2D
#
Signal2D(
t1: FloatArray | None = None,
t2: FloatArray | None = None,
amplitudes: ndarray | None = None,
t1_unit: TimeUnit = MICROSECOND,
t2_unit: TimeUnit = MICROSECOND,
metadata: dict[str, Any] | None = None,
reference_frequency_hz: float | None = None,
carrier_offset_hz_1: float | None = None,
carrier_offset_hz_2: float | None = None,
reference_signal_f1: Signal1D | None = None,
reference_signal_f2: Signal1D | None = None,
f1_reference_frequency_hz: float | None = None,
f2_reference_frequency_hz: float | None = None,
)
2D time-domain signal for NMR experiments (e.g., COSY, HSQC).
Attributes:
| Name | Type | Description |
|---|---|---|
t1 |
FloatArray
|
Time coordinates for indirect dimension (axis 1) |
t2 |
FloatArray
|
Time coordinates for direct dimension (axis 2) |
amplitudes |
ndarray
|
2D complex amplitude array with shape (len(t1), len(t2)) |
t1_unit, |
t2_unit
|
Time units for each axis |
processing_history
class-attribute
instance-attribute
#
processing_history: ProcessingHistory | None = (
betterproto2.field(
10, betterproto2.TYPE_MESSAGE, optional=True
)
)
Processing history - read-only audit log of all operations applied to this signal
history
property
#
Read-only access to processing history entries.
Returns:
| Type | Description |
|---|---|
Sequence[ProcessingHistoryEntry]
|
Immutable sequence of history entries. Returns empty tuple if |
Sequence[ProcessingHistoryEntry]
|
no history has been recorded yet. |
metadata
class-attribute
instance-attribute
#
metadata: dict[str, str] = betterproto2.field(
4,
betterproto2.TYPE_MAP,
map_meta=betterproto2.map_meta(
betterproto2.TYPE_STRING, betterproto2.TYPE_STRING
),
)
Optional metadata
_axis_1
class-attribute
instance-attribute
#
Exactly two time/spatial axes (enforced by validation)
e.g., t1
_axis_2
class-attribute
instance-attribute
#
e.g., t2
_amplitudes
class-attribute
instance-attribute
#
_amplitudes: NdComplexArray | None = betterproto2.field(
3, betterproto2.TYPE_MESSAGE, optional=True
)
2D complex amplitude data (shape = [N, M])
visualization_handler
property
writable
#
Plugin visualization handler ID (e.g., 'nanalysis:cosy_2d').
f1_reference_frequency_hz
property
writable
#
Reference frequency for F1 (indirect) dimension, for heteronuclear PPM conversion.
f2_reference_frequency_hz
property
writable
#
Reference frequency for F2 (direct) dimension, for heteronuclear PPM conversion.
sampling_rate_hz_t1
property
#
Sampling rate in Hz for t1 (indirect) dimension.
sampling_rate_hz_t2
property
#
Sampling rate in Hz for t2 (direct) dimension.
Signal1D
#
Signal1D(
time_points: FloatArray | None = None,
amplitudes: NumericArray | None = None,
time_unit: TimeUnit = MICROSECOND,
metadata: dict[str, Any] | None = None,
reference_frequency_hz: float | None = None,
carrier_offset_hz: float | None = None,
)
Time-domain 1D signal.
Attributes:
| Name | Type | Description |
|---|---|---|
time_points |
FloatNdArray
|
Time coordinates of the signal |
amplitudes |
Signal amplitudes (can be complex) |
|
time_unit |
Unit of time coordinates |
|
metadata |
dict[str, str]
|
Optional metadata dictionary |
processing_history
class-attribute
instance-attribute
#
processing_history: ProcessingHistory | None = (
betterproto2.field(
6, betterproto2.TYPE_MESSAGE, optional=True
)
)
Processing history - read-only audit log of all operations applied to this signal
history
property
#
Read-only access to processing history entries.
Returns:
| Type | Description |
|---|---|
Sequence[ProcessingHistoryEntry]
|
Immutable sequence of history entries. Returns empty tuple if |
Sequence[ProcessingHistoryEntry]
|
no history has been recorded yet. |
metadata
class-attribute
instance-attribute
#
metadata: dict[str, str] = betterproto2.field(
3,
betterproto2.TYPE_MAP,
map_meta=betterproto2.map_meta(
betterproto2.TYPE_STRING, betterproto2.TYPE_STRING
),
)
Optional metadata
visualization_handler
property
writable
#
Plugin visualization handler ID (e.g., 'nanalysis:cosy_2d').
time_points
instance-attribute
#
extract_echo_amplitudes
#
extract_echo_amplitudes(
echo_spacing_ms: float, n_echoes: int | None = None
) -> tuple[ndarray, ndarray]
Extract echo peak amplitudes from raw CPMG signal.
For pre-processed data where each point IS an echo amplitude, this simply constructs the time axis from the echo spacing.
For raw interleaved data (full echo shapes), this finds the maximum of each echo window.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
echo_spacing_ms
|
float
|
Time between echoes in milliseconds. |
required |
n_echoes
|
int | None
|
Number of echoes to extract. If None, uses all data. |
None
|
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray]
|
(echo_times_s, echo_amplitudes) — times in seconds. |
compute_t2_distribution
#
compute_t2_distribution(
echo_spacing_ms: float | None = None,
t_min: float = 1e-05,
t_max: float = 10.0,
n_points: int = 200,
alpha: float | None = None,
) -> RelaxationDistribution
Compute T2 distribution via Inverse Laplace Transform.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
echo_spacing_ms
|
float | None
|
Echo spacing in ms. If None, inferred from time_points. |
None
|
t_min
|
float
|
Minimum T2 in seconds for the distribution grid. |
1e-05
|
t_max
|
float
|
Maximum T2 in seconds for the distribution grid. |
10.0
|
n_points
|
int
|
Number of points in the T2 grid. |
200
|
alpha
|
float | None
|
Regularization parameter (None = auto via GCV). |
None
|
Returns:
| Type | Description |
|---|---|
RelaxationDistribution
|
RelaxationDistribution with the T2 spectrum. |
fit_multiexponential
#
fit_multiexponential(
echo_spacing_ms: float | None = None,
n_components: int | Literal["auto"] = "auto",
max_components: int = 4,
) -> MultiExponentialResult
Fit discrete multi-exponential decay to the echo train.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
echo_spacing_ms
|
float | None
|
Echo spacing in ms. If None, inferred from time_points. |
None
|
n_components
|
int | Literal['auto']
|
Number of components, or "auto" for BIC-based selection. |
'auto'
|
max_components
|
int
|
Maximum components to try when n_components="auto". |
4
|
Returns:
| Type | Description |
|---|---|
MultiExponentialResult
|
MultiExponentialResult with fitted time constants and amplitudes. |
pad_zeros
#
Pad signal with zeros to increase frequency resolution after FFT.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factor
|
float | None
|
Zero-fill factor. If None, pads to next power of 2. |
None
|
Returns:
| Type | Description |
|---|---|
Self
|
Self for method chaining |
convert_time_unit
#
Convert signal to different time unit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_unit
|
TimeUnit
|
Target time unit |
required |
Returns:
| Type | Description |
|---|---|
Self
|
Self for method chaining |
trim_dead_time
#
trim_dead_time(
threshold_ratio: float = 0.1,
max_dead_time: float | None = None,
dead_time_unit: TimeUnit | None = None,
) -> Self
Remove dead time from the beginning of the signal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
threshold_ratio
|
float
|
Signal threshold as ratio of max amplitude |
0.1
|
max_dead_time
|
float | None
|
Maximum dead time to consider |
None
|
dead_time_unit
|
TimeUnit | None
|
Unit for max_dead_time (defaults to signal's time unit) |
None
|
Returns:
| Type | Description |
|---|---|
Self
|
Self for method chaining |
get_upper_envelope
#
Create an upper-envelope of the signal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
smoothing_kernel_factor
|
float
|
Factor to determine smoothing kernel size |
70
|
Returns:
| Type | Description |
|---|---|
Self
|
New signal containing the upper envelope |
align_to
#
align_to(
reference: Self,
max_shift_seconds: float = 0.02,
resolution: int = 3,
fast: bool = False,
) -> Self
Cut the signal to align with the reference.
Cross-correlates data within region of interest at a precision of 1/res. If data is cross-correlated at native resolution (i.e. res=1), this function can only achieve integer precision.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reference
|
Self
|
Signal to align to. |
required |
max_shift_seconds
|
float
|
Max shift in seconds. Defaults to 0.02. |
0.02
|
resolution
|
int
|
Resolution of phase alignment. Defaults to 3. |
3
|
fast
|
bool
|
Whether to use a faster version of the algorithm. Defaults to False. |
False
|
Returns:
| Type | Description |
|---|---|
Self
|
Self for method chaining |
apodize
#
apodize(
func: Callable[[ndarray], ndarray] | WindowType,
*,
lb: float = 1.0,
sigma: float = 0.3,
alpha: float = 5.0,
) -> Self
Apply apodization (window function) to the signal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
Callable[[ndarray], ndarray] | WindowType
|
Either a callable apodization function that takes range [0;1] and returns weights, or a string window type from: "none", "exponential", "gaussian", "hamming", "hann", "blackman", "blackmanharris", "kaiser", "bartlett", "cosine", "tukey" |
required |
lb
|
float
|
Line broadening factor for exponential window (Hz). Default 1.0. |
1.0
|
sigma
|
float
|
Standard deviation for gaussian window (0-0.5 range). Default 0.3. |
0.3
|
alpha
|
float
|
Shape parameter for kaiser (beta) or tukey (alpha) windows. Default 5.0. |
5.0
|
Returns:
| Type | Description |
|---|---|
Self
|
Self for method chaining. |
to_spectrum
#
to_spectrum(
fft_method: Literal[
"real", "full", "standard"
] = "real",
window: WindowType | None = None,
window_lb: float = 1.0,
window_sigma: float = 0.3,
window_alpha: float = 5.0,
) -> Spectrum1D
Convert signal to frequency spectrum.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fft_method
|
Literal['real', 'full', 'standard']
|
FFT computation method ("real", "full", "standard"). |
'real'
|
window
|
WindowType | None
|
Optional window function to apply before FFT. Options: "none", "exponential", "gaussian", "hamming", "hann", "blackman", "blackmanharris", "kaiser", "bartlett", "cosine", "tukey". |
None
|
window_lb
|
float
|
Line broadening for exponential window (Hz). Default 1.0. |
1.0
|
window_sigma
|
float
|
Sigma for gaussian window (0-0.5). Default 0.3. |
0.3
|
window_alpha
|
float
|
Alpha/beta for kaiser/tukey windows. Default 5.0. |
5.0
|
Returns:
| Type | Description |
|---|---|
Spectrum1D
|
Spectrum object. |
apply_window
#
Apply windowing function to the signal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
window_func
|
Callable[[ndarray], ndarray]
|
Function that takes array of length N and returns window |
required |
Returns:
| Type | Description |
|---|---|
Self
|
Self for method chaining |
normalize
#
Normalize signal amplitudes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
method
|
Literal['max', 'rms', 'unit']
|
Normalization method: - "max": Divide by maximum absolute value - "rms": Divide by RMS value - "unit": Divide by L2 norm |
'max'
|
Returns:
| Type | Description |
|---|---|
Self
|
Self for method chaining |
from_proto
classmethod
#
Shallow-copy underscored proto storage into our instance.
_init_history
#
Initialize the processing history.
Called from init of Signal1D/Spectrum1D. Always creates a ProcessingHistory instance - history is always enabled.
_record_history_entry
#
_record_history_entry(
operation: str,
parameters: dict[str, str],
shape_before: tuple[int, ...],
shape_after: tuple[int, ...],
source: str = "tqt_nmr",
) -> None
Record a processing operation to the history.
This is an internal method - not exposed to users. Called by @track_operation decorator and TrackedArray.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operation
|
str
|
Name of the operation (e.g., "correct_phase_manual"). |
required |
parameters
|
dict[str, str]
|
Operation parameters as string key-value pairs. |
required |
shape_before
|
tuple[int, ...]
|
Shape of amplitudes before operation. |
required |
shape_after
|
tuple[int, ...]
|
Shape of amplitudes after operation. |
required |
source
|
str
|
Source of the operation (e.g., "tqt_nmr", "numpy"). |
'tqt_nmr'
|
_copy_history_to
#
Copy processing history to another object.
Used by copy() methods to preserve history lineage.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
Self
|
Object to copy history to. |
required |
apodize
#
apodize(
window: WindowType = "exponential",
axis: Literal["t1", "t2", "both"] = "both",
*,
lb: float = 1.0,
sigma: float = 0.3,
alpha: float = 5.0,
) -> Self
Apply apodization (window function) to the 2D signal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
window
|
WindowType
|
Window type from: "none", "exponential", "gaussian", "hamming", "hann", "blackman", "blackmanharris", "kaiser", "bartlett", "cosine", "tukey". |
'exponential'
|
axis
|
Literal['t1', 't2', 'both']
|
Which axis to apply window to ("t1", "t2", or "both"). |
'both'
|
lb
|
float
|
Line broadening for exponential window (Hz). Default 1.0. |
1.0
|
sigma
|
float
|
Sigma for gaussian window (0-0.5). Default 0.3. |
0.3
|
alpha
|
float
|
Alpha/beta for kaiser/tukey windows. Default 5.0. |
5.0
|
Returns:
| Type | Description |
|---|---|
Self
|
Self for method chaining. |
to_spectrum
#
to_spectrum(
reference_frequency_hz: float | None = None,
window: WindowType | None = None,
window_axis: Literal["t1", "t2", "both"] = "both",
window_lb: float = 1.0,
window_sigma: float = 0.3,
window_alpha: float = 5.0,
zero_fill_f1: int | None = None,
zero_fill_f2: int | None = None,
shift_f1: bool = True,
shift_f2: bool = True,
tppi_mode: Literal[
"none", "correct", "correct_and_half", "half_only"
]
| None = None,
tppi_keep_upper: bool = False,
fft_axes: Literal["both", "t2", "t1", "auto"] = "auto",
) -> Spectrum2D
Convert 2D signal to 2D frequency spectrum via FFT.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reference_frequency_hz
|
float | None
|
Reference frequency for PPM calculations. |
None
|
window
|
WindowType | None
|
Optional window function to apply before FFT. Options: "none", "exponential", "gaussian", "hamming", "hann", "blackman", "blackmanharris", "kaiser", "bartlett", "cosine", "tukey". |
None
|
window_axis
|
Literal['t1', 't2', 'both']
|
Which axis to apply window to ("t1", "t2", or "both"). |
'both'
|
window_lb
|
float
|
Line broadening for exponential window (Hz). Default 1.0. |
1.0
|
window_sigma
|
float
|
Sigma for gaussian window (0-0.5). Default 0.3. |
0.3
|
window_alpha
|
float
|
Alpha/beta for kaiser/tukey windows. Default 5.0. |
5.0
|
zero_fill_f1
|
int | None
|
Zero-fill factor for F1 dimension (None = auto: 4x if < 128 points, else next power of 2) |
None
|
zero_fill_f2
|
int | None
|
Zero-fill factor for F2 dimension (None = auto: next power of 2) |
None
|
shift_f1
|
bool
|
Apply fftshift to F1 axis (default True). Set False for TPPI acquisition. |
True
|
shift_f2
|
bool
|
Apply fftshift to F2 axis (default True). |
True
|
tppi_mode
|
Literal['none', 'correct', 'correct_and_half', 'half_only'] | None
|
TPPI/half-spectrum processing mode: - None or "none": No TPPI processing (default) - "correct": Apply TPPI correction only (multiply odd rows by -1) - "correct_and_half": Apply TPPI correction AND extract half of F1 spectrum - "half_only": Extract half of F1 spectrum without TPPI correction (for non-phase-sensitive acquisitions like CPMG, JRES) |
None
|
tppi_keep_upper
|
bool
|
Which half of F1 to keep when extracting: - False (default): keep lower half (frequencies < carrier) - for MIRRORIMAGE=0 - True: keep upper half (frequencies >= carrier) - for MIRRORIMAGE=1 |
False
|
fft_axes
|
Literal['both', 't2', 't1', 'auto']
|
Which axes to FFT: - "auto" (default): auto-detect from axis roles. If t1 has PARAMETER role, only FFT along t2 (row-wise 1D). Otherwise full 2D FFT. - "both": Full 2D FFT (standard for COSY, HSQC, etc.) - "t2": FFT only along t2 (direct dimension). Keeps t1 as-is. Use for relaxation experiments (T1, T2, CPMG, DOSY). - "t1": FFT only along t1 (indirect dimension). Keeps t2 as-is. |
'auto'
|
Returns:
| Type | Description |
|---|---|
Spectrum2D
|
Spectrum2D object. |
_to_spectrum_1d_rows
#
_to_spectrum_1d_rows(
fft_axis: Literal["t2", "t1"],
reference_frequency_hz: float | None = None,
window: WindowType | None = None,
window_lb: float = 1.0,
window_sigma: float = 0.3,
window_alpha: float = 5.0,
) -> Spectrum2D
FFT along one axis only, keeping the other as parameter values.
For relaxation experiments (T1/T2/CPMG/DOSY), the indirect axis is a parameter (delay, gradient strength), not a time dimension. Each row (or column) is an independent FID that gets its own 1D FFT.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fft_axis
|
Literal['t2', 't1']
|
Which axis to FFT ("t2" = row-wise, "t1" = column-wise). |
required |
reference_frequency_hz
|
float | None
|
Reference frequency for PPM calculations. |
None
|
window
|
WindowType | None
|
Window function for apodization before FFT. |
None
|
window_lb
|
float
|
Line broadening parameter. |
1.0
|
window_sigma
|
float
|
Gaussian sigma parameter. |
0.3
|
window_alpha
|
float
|
Kaiser/tukey alpha parameter. |
5.0
|
normalize
#
Normalize signal amplitudes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
method
|
Literal['max', 'rms', 'unit']
|
Normalization method: - "max": Divide by maximum absolute value - "rms": Divide by RMS value - "unit": Divide by L2 norm |
'max'
|
Returns:
| Type | Description |
|---|---|
Self
|
Self for method chaining |
pad_zeros
#
Pad signal with zeros to increase resolution after FFT.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factor_t1
|
float | None
|
Zero-fill factor for t1 dimension (None = next power of 2) |
None
|
factor_t2
|
float | None
|
Zero-fill factor for t2 dimension (None = next power of 2) |
None
|
Returns:
| Type | Description |
|---|---|
Self
|
Self for method chaining |
correct_tppi
#
Apply TPPI (Time-Proportional Phase Incrementation) correction.
In TPPI acquisition, the phase of the first pulse in the indirect dimension is incremented by 90° for each t1 increment. This effectively shifts the carrier frequency by half the spectral width in F1.
To correct for this before FFT, we multiply every other row by -1, which undoes the phase alternation and properly centers the spectrum in F1.
This method should be called before FFT for data acquired with TPPI.
Returns:
| Type | Description |
|---|---|
Self
|
Self for method chaining |
get_base_signal
#
Get the main signal without reference data.
Returns a copy of this signal with reference fields set to None.
get_reference_f1
#
get_reference_f1() -> Signal1D | None
Get F1 (indirect dimension) reference signal.
get_reference_f2
#
get_reference_f2() -> Signal1D | None
Get F2 (direct dimension) reference signal.
_setup_from_arrays
#
_setup_from_arrays(
t1: FloatArray,
t2: FloatArray,
amplitudes: ndarray,
t1_unit: TimeUnit,
t2_unit: TimeUnit,
) -> None
_sync_numpy_to_proto
#
Override to sync reference signals before serialization.