#[macro_export]
macro_rules! load_polars_df {
($df:expr) => {{
let df = $df;
let mut dataset: $crate::core::data::Dataset = $crate::core::data::Dataset::new();
for column in df.columns() {
let series = column.as_series().ok_or_else(|| {
$crate::error::ChartonError::Data(format!(
"Column '{}' is not a Series",
column.name()
))
})?;
let name = series.name().to_string();
match series.dtype() {
polars::prelude::DataType::Float64 => {
let ca = series.f64().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<f64>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Float32 => {
let ca = series.f32().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<f32>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Int64 => {
let ca = series.i64().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<i64>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Int32 => {
let ca = series.i32().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<i32>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Int16 => {
let ca = series.i16().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<i16>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Int8 => {
let ca = series.i8().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<i8>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::UInt64 => {
let ca = series.u64().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<u64>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::UInt32 => {
let ca = series.u32().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<u32>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::String => {
let ca = series.str().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<String>> = ca
.into_iter()
.map(|opt| opt.map(|s| s.to_string()))
.collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Categorical(_, _)
| polars::prelude::DataType::Enum(_, _) => {
let ca = series.cat32().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' categorical error: {}",
name, e
))
})?;
let physical = ca.physical();
let keys: Vec<u32> = physical.into_no_null_iter().collect();
let values: Vec<String> = ca
.iter_str()
.map(|opt| opt.unwrap_or("").to_string())
.collect();
let validity = if physical.null_count() > 0 {
physical
.chunks()
.get(0)
.and_then(|array| array.validity().map(|v| v.as_slice().0.to_vec()))
} else {
None
};
let cv = $crate::core::data::ColumnVector::from_categorical(keys, values, validity);
dataset.add_column(name, cv)?;
}
polars::prelude::DataType::Boolean => {
let ca = series.bool().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<bool>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Datetime(unit, _tz) => {
let ca = series.datetime().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' datetime error: {}",
name, e
))
})?;
let multiplier = match unit {
polars::prelude::TimeUnit::Milliseconds => 1_000_000i128,
polars::prelude::TimeUnit::Microseconds => 1_000i128,
polars::prelude::TimeUnit::Nanoseconds => 1i128,
};
let dt_vec: Vec<Option<$crate::prelude::ctime::OffsetDateTime>> = ca
.physical()
.into_iter()
.map(|opt_ts| {
opt_ts.and_then(|ts| {
let nanos = (ts as i128) * multiplier;
$crate::prelude::ctime::OffsetDateTime::from_unix_timestamp_nanos(nanos).ok()
})
})
.collect();
dataset.add_column(name, dt_vec)?;
}
polars::prelude::DataType::Date => {
let ca = series.date().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' date error: {}",
name, e
))
})?;
let unix_epoch = $crate::prelude::ctime::Date::from_calendar_date(
1970,
$crate::prelude::ctime::Month::January,
1,
).unwrap();
let date_vec: Vec<Option<$crate::prelude::ctime::Date>> = ca
.physical()
.into_iter()
.map(|opt_days| {
opt_days.and_then(|d| {
unix_epoch.checked_add($crate::prelude::ctime::Duration::days(d as i64))
})
})
.collect();
dataset.add_column(name, date_vec)?;
}
polars::prelude::DataType::Time => {
let ca = series.time().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' time error: {}",
name, e
))
})?;
let time_vec: Vec<Option<$crate::prelude::ctime::Time>> = ca
.physical()
.into_iter()
.map(|opt_nanos| {
opt_nanos.and_then(|n| {
$crate::prelude::ctime::Time::from_hms_nano(0, 0, 0, n as u32).ok()
})
})
.collect();
dataset.add_column(name, time_vec)?;
}
polars::prelude::DataType::Duration(unit) => {
let ca = series.duration().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' duration error: {}",
name, e
))
})?;
let multiplier = match unit {
polars::prelude::TimeUnit::Milliseconds => 1_000_000,
polars::prelude::TimeUnit::Microseconds => 1_000,
polars::prelude::TimeUnit::Nanoseconds => 1,
};
let dur_vec: Vec<Option<$crate::prelude::ctime::Duration>> = ca
.physical()
.into_iter()
.map(|opt_v| {
opt_v.map(|v| {
let total_nanos = v * multiplier;
$crate::prelude::ctime::Duration::nanoseconds(total_nanos)
})
})
.collect();
dataset.add_column(name, dur_vec)?;
}
_ => {
return Err($crate::error::ChartonError::Data(format!(
"Unsupported Polars DataType '{:?}' in column '{}'.",
series.dtype(),
name
))
.into());
}
}
}
let res: std::result::Result<$crate::core::data::Dataset, $crate::error::ChartonError> =
Ok(dataset);
res
}};
}
#[macro_export]
macro_rules! chart {
(&$ds:expr) => {
$crate::chart::Chart::build($ds.clone())
};
($ds:expr) => {
$crate::chart::Chart::build($ds)
};
($( $(&)? $col:ident ),+ $(,)?) => {{
let mut ds = $crate::core::data::Dataset::new();
let mut result = Ok(ds);
$(
// We pass the tokens exactly as matched to the internal parser
result = $crate::chart!(@parse_col result, $col);
)+
result.and_then(|ds| $crate::chart::Chart::build(ds))
}};
(@parse_col $res:ident, &$name:ident) => {
$res.and_then(|mut d| {
d.add_column(stringify!($name), $name.clone())?;
Ok(d)
})
};
(@parse_col $res:ident, $name:ident) => {
$res.and_then(|mut d| {
d.add_column(stringify!($name), $name.clone())?;
Ok(d)
})
};
}
#[macro_export]
macro_rules! load_polars_v44_52 {
($df:expr) => {{
let df = $df;
let mut dataset: $crate::core::data::Dataset = $crate::core::data::Dataset::new();
for column in df.get_columns() {
let series = column.as_series().ok_or_else(|| {
$crate::error::ChartonError::Data(format!(
"Column '{}' is not a Series",
column.name()
))
})?;
let name = series.name().to_string();
match series.dtype() {
polars::prelude::DataType::Float64 => {
let ca = series.f64().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<f64>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Float32 => {
let ca = series.f32().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<f32>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Int64 => {
let ca = series.i64().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<i64>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Int32 => {
let ca = series.i32().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<i32>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Int16 => {
let ca = series.i16().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<i16>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Int8 => {
let ca = series.i8().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<i8>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::UInt64 => {
let ca = series.u64().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<u64>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::UInt32 => {
let ca = series.u32().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<u32>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::String => {
let ca = series.str().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<String>> = ca
.into_iter()
.map(|opt| opt.map(|s| s.to_string()))
.collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Boolean => {
let ca = series.bool().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' cast error: {}",
name, e
))
})?;
let vec: Vec<Option<bool>> = ca.into_iter().collect();
dataset.add_column(name, vec)?;
}
polars::prelude::DataType::Datetime(unit, _tz) => {
let ca = series.datetime().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' datetime error: {}",
name, e
))
})?;
let multiplier = match unit {
polars::prelude::TimeUnit::Milliseconds => 1_000_000i128,
polars::prelude::TimeUnit::Microseconds => 1_000i128,
polars::prelude::TimeUnit::Nanoseconds => 1i128,
};
let dt_vec: Vec<Option<$crate::prelude::ctime::OffsetDateTime>> = ca
.physical()
.into_iter()
.map(|opt_ts| {
opt_ts.and_then(|ts| {
let nanos = (ts as i128) * multiplier;
$crate::prelude::ctime::OffsetDateTime::from_unix_timestamp_nanos(nanos).ok()
})
})
.collect();
dataset.add_column(name, dt_vec)?;
}
polars::prelude::DataType::Date => {
let ca = series.date().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' date error: {}",
name, e
))
})?;
let unix_epoch = $crate::prelude::ctime::Date::from_calendar_date(
1970,
$crate::prelude::ctime::Month::January,
1,
).unwrap();
let date_vec: Vec<Option<$crate::prelude::ctime::Date>> = ca
.physical()
.into_iter()
.map(|opt_days| {
opt_days.and_then(|d| {
unix_epoch.checked_add($crate::prelude::ctime::Duration::days(d as i64))
})
})
.collect();
dataset.add_column(name, date_vec)?;
}
polars::prelude::DataType::Time => {
let ca = series.time().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' time error: {}",
name, e
))
})?;
let time_vec: Vec<Option<$crate::prelude::ctime::Time>> = ca
.physical()
.into_iter()
.map(|opt_nanos| {
opt_nanos.and_then(|n| {
$crate::prelude::ctime::Time::from_hms_nano(0, 0, 0, n as u32).ok()
})
})
.collect();
dataset.add_column(name, time_vec)?;
}
polars::prelude::DataType::Duration(unit) => {
let ca = series.duration().map_err(|e| {
$crate::error::ChartonError::Data(format!(
"Column '{}' duration error: {}",
name, e
))
})?;
let multiplier = match unit {
polars::prelude::TimeUnit::Milliseconds => 1_000_000,
polars::prelude::TimeUnit::Microseconds => 1_000,
polars::prelude::TimeUnit::Nanoseconds => 1,
};
let dur_vec: Vec<Option<$crate::prelude::ctime::Duration>> = ca
.physical()
.into_iter()
.map(|opt_v| {
opt_v.map(|v| {
let total_nanos = v * multiplier;
$crate::prelude::ctime::Duration::nanoseconds(total_nanos)
})
})
.collect();
dataset.add_column(name, dur_vec)?;
}
_ => {
return Err($crate::error::ChartonError::Data(format!(
"Unsupported Polars DataType '{:?}' in column '{}'.",
series.dtype(),
name
))
.into());
}
}
}
let res: std::result::Result<$crate::core::data::Dataset, $crate::error::ChartonError> =
Ok(dataset);
res
}};
}