///|
pub fn resample_linear(
points : Array[SignalPoint],
step : Int64,
) -> Array[SignalPoint] {
let result : Array[SignalPoint] = []
if points.length() == 0 || step <= 0L {
return result
}
let mut timestamp = points[0].timestamp
let last = points[points.length() - 1].timestamp
let mut cursor = 0
while timestamp <= last {
while cursor + 1 < points.length() &&
points[cursor + 1].timestamp < timestamp {
cursor += 1
}
if cursor + 1 >= points.length() {
result.push(SignalPoint::new(timestamp, points[cursor].value))
timestamp += step
continue
}
let left = points[cursor]
let right = points[cursor + 1]
let value = if right.timestamp == left.timestamp {
right.value
} else {
left.value +
(right.value - left.value) *
(timestamp - left.timestamp).to_double() /
(right.timestamp - left.timestamp).to_double()
}
result.push(SignalPoint::new(timestamp, value))
timestamp += step
}
result
}
///|
pub fn align_by_timestamp(
left : Array[SignalPoint],
right : Array[SignalPoint],
) -> (Array[Double], Array[Double]) {
let a : Array[Double] = []
let b : Array[Double] = []
let mut i = 0
let mut j = 0
while i < left.length() && j < right.length() {
if left[i].timestamp == right[j].timestamp {
a.push(left[i].value)
b.push(right[j].value)
i += 1
j += 1
} else if left[i].timestamp < right[j].timestamp {
i += 1
} else {
j += 1
}
}
(a, b)
}
///|
pub fn lag_points(
points : Array[SignalPoint],
lag : Int64,
) -> Array[SignalPoint] {
let result : Array[SignalPoint] = []
for point in points {
result.push(
SignalPoint::new(
point.timestamp + lag,
point.value,
sequence=point.sequence,
),
)
}
result
}
///|
pub fn rolling_quantile(
values : Array[Double],
window_size : Int,
probability : Double,
) -> Array[Double] {
let result : Array[Double] = []
let window = DoubleWindow::new(window_size)
for value in values {
ignore(window.push(value))
result.push(window.quantile(probability))
}
result
}
///|
pub fn interpolate_points(
points : Array[SignalPoint],
step : Int64,
) -> Array[SignalPoint] {
resample_linear(points, step)
}