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
_time_axis
class-attribute
instance-attribute
#
Exactly one time axis (enforced by validation)
_amplitudes
class-attribute
instance-attribute
#
_amplitudes: NdComplexArray | None = betterproto2.field(
2, betterproto2.TYPE_MESSAGE, optional=True
)
1D complex amplitude data (shape = [N])
visualization_handler
property
writable
#
Plugin visualization handler ID (e.g., 'nanalysis:cosy_2d').
time_points
instance-attribute
#
_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 |
extract_echo_amplitudes
#
extract_echo_amplitudes(
echo_spacing_ms: float,
n_echoes: int | None = None,
use_real: bool = False,
) -> tuple[ndarray, ndarray]
Extract echo amplitudes from a pre-processed CPMG signal.
Each sample of amplitudes is treated as one echo amplitude, and the
time axis is reconstructed from echo_spacing_ms.
Limitation
This does not handle raw interleaved data containing full echo shapes; it never searches for the maximum within an echo window. (An earlier version of this docstring claimed it did — it never has.) Raw echo trains must be reduced to one point per echo beforehand.
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
|
use_real
|
bool
|
Use the phased real part instead of the magnitude.
Default False (magnitude). Magnitude mode makes the noise floor
Rician (strictly positive, non-zero mean), which biases a
subsequent T2 distribution towards a spurious long-T2 component.
If the data is properly phased, prefer |
False
|
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,
use_real: bool = False,
) -> RelaxationDistribution
Compute T2 distribution via Inverse Laplace Transform.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
echo_spacing_ms
|
float | None
|
Echo spacing in ms. If None, the echo times are taken
from |
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
|
use_real
|
bool
|
Use the phased real part instead of the magnitude.
Default False (magnitude). Magnitude mode gives a Rician noise
floor with a positive mean, which biases the recovered T2
distribution towards a spurious long-T2 component. Use
|
False
|
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,
use_real: bool = False,
) -> 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, the echo times are taken
from |
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
|
use_real
|
bool
|
Use the phased real part instead of the magnitude
(default False). See :meth: |
False
|
Returns:
| Type | Description |
|---|---|
MultiExponentialResult
|
MultiExponentialResult with fitted time constants and amplitudes. |
Raises:
| Type | Description |
|---|---|
ImportError
|
If the |
_echo_data
#
Return the decay data as float, either magnitude or the real part.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
use_real
|
bool
|
If True use |
required |
_time_points_seconds
#
Time points converted to seconds using the signal's own time unit.
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.
The original time origin is preserved: the retained points keep their
original time values, so the acquisition delay that first-order phase
correction depends on is not silently discarded. The removed delay is
also recorded in metadata["dead_time_removed"] (in the signal's time
unit) and the number of dropped samples in
metadata["dead_time_removed_samples"].
Limitation
An FID normally has its maximum at t=0, so abs(signal) > threshold
is almost always already true at the very first sample and
start_idx comes out as 0 — i.e. for ordinary FIDs this method is
effectively a no-op. It is only useful for signals whose leading
samples are genuinely suppressed (e.g. hardware-blanked receivers or
echo-like data). Use max_dead_time to trim a known fixed delay
instead of relying on the threshold test.
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.
A positive shift means this signal lags the reference and leading
samples are dropped. A negative shift means this signal leads the
reference; |shift| samples are zero-padded at the front and the time
axis extended backwards by the same amount.
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 | None = None,
sigma: float = 0.3,
alpha: float = 5.0,
gb: float | None = None,
) -> 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 | None
|
Line broadening factor for exponential window, in Hz
(Lorentzian FWHM). |
None
|
sigma
|
float
|
Gaussian width as a dimensionless fraction of the acquisition
time (0-0.5 range). Default 0.3. Ignored when |
0.3
|
alpha
|
float
|
Shape parameter for kaiser (beta) or tukey (alpha) windows. Default 5.0. |
5.0
|
gb
|
float | None
|
Gaussian line broadening in Hz (Gaussian FWHM). When provided,
the gaussian window becomes physically parameterized (consistent
with |
None
|
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 | None = None,
window_sigma: float = 0.3,
window_alpha: float = 5.0,
zero_fill: float | None = None,
first_point_scale: bool = True,
) -> Spectrum1D
Convert signal to frequency spectrum.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fft_method
|
Literal['real', 'full', 'standard']
|
FFT computation method ("real", "full", "standard").
Note: "standard" is an O(N^2) dense DFT and is refused above
|
'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 | None
|
Line broadening for exponential window (Hz). |
None
|
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
|
float | None
|
Optional zero-fill applied to a copy of the signal before
the FFT, using |
None
|
first_point_scale
|
bool
|
Halve |
True
|
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 |
adaptive_line_broadening_hz
#
Exponential line broadening (Hz) measured from this signal.
Returns None when the signal carries no line whose width can be
measured.
_get_window
#
_get_window(
window_type: WindowType,
n: int,
*,
lb: float = 1.0,
sigma: float = 0.3,
alpha: float = 5.0,
gb: float | None = None,
) -> ndarray
Generate a window array for apodization.
Thin wrapper around :func:generate_apodization_window.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
window_type
|
WindowType
|
Type of window function. |
required |
n
|
int
|
Number of points. |
required |
lb
|
float
|
Line broadening for exponential, in Hz. |
1.0
|
sigma
|
float
|
Dimensionless gaussian width (fraction of acquisition time). |
0.3
|
alpha
|
float
|
Alpha/beta for kaiser/tukey. |
5.0
|
gb
|
float | None
|
Gaussian line broadening in Hz (takes precedence over |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Window array of length n, starting at ~1 and decaying. |
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.