Source code for vallenae.features.acoustic_emission

from __future__ import annotations

import numpy as np


[docs] def peak_amplitude(data: np.ndarray) -> float: """ Compute maximum absolute amplitude. Args: data: Input array Returns: Peak amplitude of the input array """ return np.max(np.abs(data))
[docs] def peak_amplitude_index(data: np.ndarray) -> int: """ Compute index of peak amplitude. Args: data: Input array Returns: Index of peak amplitude """ return np.argmax(np.abs(data))
def _mask_above_threshold(data: np.ndarray, threshold: float) -> np.ndarray: return (data >= threshold) | (data <= -threshold)
[docs] def is_above_threshold(data: np.ndarray, threshold: float) -> bool: """ Checks if absolute amplitudes are above threshold. Args: data: Input array threshold: Threshold amplitude Returns: True if input array is above threshold, otherwise False """ return np.any(_mask_above_threshold(data, threshold))
[docs] def first_threshold_crossing(data: np.ndarray, threshold: float) -> int | None: """ Compute index of first threshold crossing. Args: data: Input array threshold: Threshold amplitude Returns: Index of first threshold crossing. None if threshold was not exceeded """ above_threshold = _mask_above_threshold(data, threshold) if above_threshold.size == 0: return None index = np.argmax(above_threshold) return index if above_threshold[index] else None
[docs] def last_threshold_crossing(data: np.ndarray, threshold: float) -> int | None: """ Compute index of last threshold crossing. Args: data: Input array threshold: Threshold amplitude Returns: Index of last threshold crossing. None if threshold was not exceeded """ index = first_threshold_crossing(data[::-1], threshold) return len(data) - 1 - index if index is not None else None
[docs] def duration(data: np.ndarray, threshold: float, samplerate: int) -> float: """ Compute the duration of a hit. Args: data: Input array (hit) threshold: Threshold amplitude samplerate: Sample rate of input array in Hz Returns: Duration in seconds """ index_first = first_threshold_crossing(data, threshold) index_last = last_threshold_crossing(data, threshold) if index_first is None or index_last is None: return 0.0 return (index_last - index_first) / samplerate
[docs] def rise_time( data: np.ndarray, threshold: float, samplerate: int, first_crossing: int | None = None, index_peak: int | None = None, ) -> float: """ Compute the rise time. The rise time is the time between the first threshold crossing and the peak amplitude. Args: data: Input array (hit) threshold: Threshold amplitude (in volts) samplerate: Sample rate of the input array first_crossing: Precomputed index of first threshold crossing to save computation time index_peak: Precomputed index of peak amplitude to save computation time Returns: Rise time in seconds """ # save some computations if pre-results are provided n_first_crossing = ( first_crossing if first_crossing is not None else first_threshold_crossing(data, threshold) ) n_max = index_peak if index_peak is not None else peak_amplitude_index(data) if n_first_crossing is None: return 0 return (n_max - n_first_crossing) / samplerate
[docs] def energy(data: np.ndarray, samplerate: int) -> float: """ Compute the energy of a hit. Energy is the integral of the squared AE-signal over time (EN 1330-9). The unit of energy is eu. 1 eu corresponds to 1e-14 V²s. Args: data: Input array (hit) samplerate: Sample rate of input array in Hz Returns: Energy of input array (hit) """ return np.sum(data**2) * 1e14 / samplerate
[docs] def signal_strength(data: np.ndarray, samplerate: int) -> float: """ Compute the signal strength of a hit. Signal strength is the integral of the rectified AE-signal over time. The unit of Signal Strength is nVs (1e-9 Vs). Args: data: Input array (hit) samplerate: Sample rate of input array in Hz Returns: Signal strength of input array (hit) """ return np.sum(np.abs(data)) * 1e9 / samplerate
[docs] def counts(data: np.ndarray, threshold: float) -> int: """ Compute the number of positive threshold crossings of a hit (counts). Args: data: Input array threshold: Threshold amplitude Returns: Number of positive threshold crossings """ above_positive_threshold = data >= threshold return np.count_nonzero(~above_positive_threshold[:-1] & above_positive_threshold[1:])
[docs] def rms(data: np.ndarray) -> float: """ Compute the root mean square (RMS) of an array. Args: data: Input array Returns: RMS of the input array References: https://en.wikipedia.org/wiki/Root_mean_square """ return np.sqrt(np.mean(data**2))