///|
pub fn signal_stats(
signal : ArrayView[Double],
) -> SignalStats raise SpectrumError {
let n = signal.length()
if n == 0 {
raise EmptySignal
}
let mut total = 0.0
let mut sum_squares = 0.0
let mut minimum = signal[0]
let mut maximum = signal[0]
for value in signal {
total = total + value
sum_squares = sum_squares + value * value
if value < minimum {
minimum = value
}
if value > maximum {
maximum = value
}
}
let count = Double::from_int(n)
let mean = total / count
let mut centered_squares = 0.0
for value in signal {
let delta = value - mean
centered_squares = centered_squares + delta * delta
}
let variance = centered_squares / count
{
count: n,
mean,
variance,
stddev: variance.sqrt(),
rms: (sum_squares / count).sqrt(),
minimum,
maximum,
peak_to_peak: maximum - minimum,
}
}
///|
pub fn center(signal : ArrayView[Double]) -> Array[Double] raise SpectrumError {
let stats = signal_stats(signal)
signal.map(value => value - stats.mean)
}
///|
pub fn detrend_linear(
signal : ArrayView[Double],
) -> Array[Double] raise SpectrumError {
let stats = signal_stats(signal)
let n = signal.length()
if n == 1 {
return [0.0]
}
let x_mean = Double::from_int(n - 1) / 2.0
let mut denominator = 0.0
let mut numerator = 0.0
for i in 0.. Array[Double] raise SpectrumError {
let stats = signal_stats(signal)
let mut scale = stats.minimum.abs()
if stats.maximum.abs() > scale {
scale = stats.maximum.abs()
}
if scale == 0.0 {
return Array::make(stats.count, 0.0)
}
signal.map(value => value / scale)
}