Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Polars integration #60

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
3 changes: 3 additions & 0 deletions downsample_rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ license = "MIT"
[dependencies]
# TODO: perhaps use polars?
argminmax = { version = "0.6.1", features = ["half"] }
# For some reason we need to explicitely add chrono, otherwise polars refuses to compile?
chrono = "0.4.31"
polars = { version = "0.33.2", features = ["lazy", "streaming", "zip_with"] }
half = { version = "2.3.1", default-features = false , features=["num-traits"], optional = true}
num-traits = { version = "0.2.17", default-features = false }
once_cell = "1"
Expand Down
115 changes: 115 additions & 0 deletions downsample_rs/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use num_traits::AsPrimitive;
use polars::prelude::{ChunkAgg, ChunkAnyValue, ChunkedArray, Float64Type};

use crate::types::Num;

Expand Down Expand Up @@ -31,3 +32,117 @@ where
self.iter().fold(0f64, |acc, &x| acc + x.as_()) as f64 / self.len() as f64
}
}

impl<T> Average for Vec<T>
where
T: Num + AsPrimitive<f64>,
{
fn average(&self) -> f64 {
self.iter().fold(0f64, |acc, &x| acc + x.as_()) as f64 / self.len() as f64
}
}

pub trait LttbParam {
type IterType: Iterator<Item = f64>;
type SliceType: LttbParam;

fn slice(&self, start_idx: usize, end_idx: usize) -> Self::SliceType;

fn get(&self, index: usize) -> f64;

fn into_iter(&self) -> Self::IterType;

fn len(&self) -> usize;

fn average(&self) -> f64;
}

impl<T> LttbParam for [T]
where
T: Num + AsPrimitive<f64>,
{
type IterType = std::vec::IntoIter<f64>;
type SliceType = std::vec::Vec<f64>;

fn slice(&self, start_idx: usize, end_idx: usize) -> Self::SliceType {
self[start_idx..end_idx].iter().map(|v| v.as_()).collect()
}

fn get(&self, index: usize) -> f64 {
self[index].as_()
}

fn into_iter(&self) -> Self::IterType {
IntoIterator::into_iter(self.iter().map(|v| v.as_()).collect::<Vec<f64>>())
}

fn len(&self) -> usize {
self.len()
}

fn average(&self) -> f64 {
Average::average(self)
}
}

impl<T> LttbParam for Vec<T>
where
T: Num + AsPrimitive<f64>,
{
type IterType = std::vec::IntoIter<f64>;
type SliceType = std::vec::Vec<f64>;

fn slice(&self, start_idx: usize, end_idx: usize) -> Self::SliceType {
self[start_idx..end_idx].iter().map(|v| v.as_()).collect()
}

fn get(&self, index: usize) -> f64 {
self[index].as_()
}

fn into_iter(&self) -> Self::IterType {
IntoIterator::into_iter(self.iter().map(|v| v.as_()).collect::<Vec<f64>>())
}

fn len(&self) -> usize {
self.len()
}

fn average(&self) -> f64 {
Average::average(self)
}
}

impl LttbParam for ChunkedArray<Float64Type> {
type IterType = std::vec::IntoIter<f64>;
type SliceType = ChunkedArray<Float64Type>;

fn slice(&self, start_idx: usize, end_idx: usize) -> Self::SliceType {
self.slice(start_idx as i64, end_idx - start_idx)
}

fn get(&self, index: usize) -> f64 {
match self
.get_any_value(index)
.unwrap()
.cast(&polars::prelude::DataType::Float64)
.unwrap()
{
polars::prelude::AnyValue::Float64(x) => x,
_ => unreachable!(), // this can never be reached, as it should have panicked when casting
}
}

fn into_iter(&self) -> Self::IterType {
// TODO: fix this so we don't do any needless copying
self.into_no_null_iter().collect::<Vec<f64>>().into_iter()
}

fn len(&self) -> usize {
self.len()
}

fn average(&self) -> f64 {
self.mean().unwrap_or(0.0)
}
}