Skip to content

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 #

history: Sequence[ProcessingHistoryEntry]

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

axis_role property writable #

axis_role: AxisRole

Physical role of this signal's time axis.

nucleus property writable #

nucleus: Nucleus

Nucleus type for this signal's time axis.

_visualization_handler class-attribute instance-attribute #

_visualization_handler: str = ''

_time_axis class-attribute instance-attribute #

_time_axis: NdAxis | None = betterproto2.field(
    1, betterproto2.TYPE_MESSAGE, optional=True
)

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])

_points_view instance-attribute #

_points_view: ndarray | None

_np_dirty_points instance-attribute #

_np_dirty_points: bool

visualization_handler property writable #

visualization_handler: str

Plugin visualization handler ID (e.g., 'nanalysis:cosy_2d').

__module__ class-attribute instance-attribute #

__module__ = GrpcSignal1D.__module__

time_points instance-attribute #

time_points: FloatNdArray = np.asarray(
    time_points, dtype=np.float64
)

amplitudes instance-attribute #

amplitudes = np.asarray(amplitudes, dtype=np.complex128)

time_unit instance-attribute #

time_unit = time_unit

reference_frequency_hz instance-attribute #

reference_frequency_hz = float(reference_frequency_hz)

carrier_offset_hz instance-attribute #

carrier_offset_hz = float(carrier_offset_hz)

duration property #

duration: float

Total duration of the signal in current time units.

duration_seconds property #

duration_seconds: float

Total duration of the signal in seconds.

sampling_rate_hz property #

sampling_rate_hz: float

Sampling rate in Hz.

is_complex property #

is_complex: bool

Whether the signal has complex amplitudes.

_init_history #

_init_history() -> None

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_history_to(other: Self) -> None

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
) -> 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_zeros(factor: float | None = None) -> Self

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_time_unit(target_unit: TimeUnit) -> Self

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 #

get_upper_envelope(
    smoothing_kernel_factor: float = 70,
) -> Self

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]) -> Self
apodize(
    func: WindowType,
    *,
    lb: float = 1.0,
    sigma: float = 0.3,
    alpha: float = 5.0,
) -> Self
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_window(
    window_func: Callable[[ndarray], ndarray],
) -> Self

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

_get_window #

_get_window(
    window_type: WindowType,
    n: int,
    *,
    lb: float = 1.0,
    sigma: float = 0.3,
    alpha: float = 5.0,
) -> ndarray

Generate a window array for apodization.

For NMR FID signals, windows must decay from 1 at t=0. Scipy's centered windows (hamming, hann, etc.) are converted to one-sided decay windows by using only their second half.

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 (Hz).

1.0
sigma float

Sigma for gaussian (0-0.5).

0.3
alpha float

Alpha/beta for kaiser/tukey.

5.0

Returns:

Type Description
ndarray

Window array of length n, starting at ~1 and decaying.

normalize #

normalize(
    method: Literal["max", "rms", "unit"] = "max",
) -> Self

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

__post_init__ #

__post_init__() -> None

__bytes__ #

__bytes__() -> bytes

load #

load(
    stream: SupportsRead[bytes], size: int | None = None
) -> Self

parse classmethod #

parse(data: bytes) -> Self

FromString classmethod #

FromString(s: bytes) -> Self

_pb_amplitudes #

_pb_amplitudes() -> NdComplexArray

_ensure_storage_initialized #

_ensure_storage_initialized() -> None

_mark_dirty #

_mark_dirty(field: str) -> None

_sync_numpy_to_proto #

_sync_numpy_to_proto() -> None

_sync_proto_to_numpy #

_sync_proto_to_numpy() -> None

_pb_axis #

_pb_axis() -> NdAxis

_ensure_axis_initialized #

_ensure_axis_initialized() -> None

to_nd #

to_nd(visualization_handler: str | None = None) -> SignalNd

copy #

copy() -> Self

Create a deep copy of this signal.

__len__ #

__len__() -> int

__getitem__ #

__getitem__(key: slice | int) -> Self

Get subset of signal.

from_proto classmethod #

from_proto(proto: Signal1D | SignalNd | None) -> Self

Shallow-copy underscored proto storage into our instance.