Path: blob/main/crates/polars-ops/src/chunked_array/peaks.rs
6939 views
use polars_core::prelude::*;1use polars_core::with_match_physical_numeric_polars_type;23pub fn peak_min_max(4column: &Column,5start: &AnyValue<'_>,6end: &AnyValue<'_>,7is_peak_max: bool,8) -> PolarsResult<BooleanChunked> {9let name = column.name().clone();10let column = column.to_physical_repr();11let column = column.as_materialized_series();12match column.dtype() {13dt if dt.is_bool() => {14let series = column.cast(&DataType::Int8)?;15let column = series.into_column();16peak_min_max(&column, start, end, is_peak_max)17},18dt if dt.is_primitive_numeric() => {19with_match_physical_numeric_polars_type!(dt, |$T| {20let ca: &ChunkedArray<$T> = column.as_ref().as_ref().as_ref();21let start = start.extract();22let end = end.extract();23Ok(if is_peak_max {24peak_max_with_start_end(ca, start, end)25} else {26peak_min_with_start_end(ca, start, end)27}.with_name(name))28})29},30dt => polars_bail!(opq = peak_max, dt),31}32}3334/// Get a boolean mask of the local maximum peaks.35pub fn peak_max_with_start_end<T: PolarsNumericType>(36ca: &ChunkedArray<T>,37start: Option<T::Native>,38end: Option<T::Native>,39) -> BooleanChunked40where41ChunkedArray<T>: for<'a> ChunkCompareIneq<&'a ChunkedArray<T>, Item = BooleanChunked>,42{43let shift_left = ca.shift_and_fill(1, start);44let shift_right = ca.shift_and_fill(-1, end);45ChunkedArray::lt(&shift_left, ca) & ChunkedArray::lt(&shift_right, ca)46}4748/// Get a boolean mask of the local minimum peaks.49pub fn peak_min_with_start_end<T: PolarsNumericType>(50ca: &ChunkedArray<T>,51start: Option<T::Native>,52end: Option<T::Native>,53) -> BooleanChunked54where55ChunkedArray<T>: for<'a> ChunkCompareIneq<&'a ChunkedArray<T>, Item = BooleanChunked>,56{57let shift_left = ca.shift_and_fill(1, start);58let shift_right = ca.shift_and_fill(-1, end);59ChunkedArray::gt(&shift_left, ca) & ChunkedArray::gt(&shift_right, ca)60}616263