use rustygraph::{TimeSeries, VisibilityGraph};
#[cfg(feature = "polars-integration")]
use rustygraph::integrations::polars::*;
#[cfg(feature = "polars-integration")]
use polars::prelude::*;
#[cfg(feature = "polars-integration")]
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("🔷 RustyGraph + Polars Integration Example\n");
println!("📊 Example 1: Basic DataFrame Conversion");
println!("{}", "=".repeat(60));
let df = df! {
"time" => &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0],
"value" => &[1.0, 3.0, 2.0, 4.0, 1.0, 3.0],
}?;
println!("Input DataFrame:");
println!("{}", df);
let series = TimeSeries::<f64>::from_polars_df(&df, "time", "value")?;
println!("\n✅ Converted to TimeSeries with {} points", series.len());
let graph = VisibilityGraph::from_series(&series).natural_visibility()?;
println!("📈 Natural Visibility Graph:");
println!(" Nodes: {}", graph.node_count);
println!(" Edges: {}", graph.edges().len());
println!(" Density: {:.4}", graph.density());
println!("\n📊 Example 2: Export Graph to DataFrame");
println!("{}", "=".repeat(60));
let graph_df = graph.to_polars_df()?;
println!("Graph properties as DataFrame:");
println!("{}", graph_df);
let edges_df = graph.edges_to_polars_df()?;
println!("\nEdges as DataFrame:");
println!("{}", edges_df);
println!("\n📊 Example 3: Batch Processing");
println!("{}", "=".repeat(60));
let multi_df = df! {
"timestamp" => &[0.0, 1.0, 2.0, 3.0, 4.0, 0.0, 1.0, 2.0, 3.0, 4.0, 0.0, 1.0, 2.0, 3.0, 4.0],
"reading" => &[1.0, 3.0, 2.0, 4.0, 1.0, 2.0, 1.0, 3.0, 2.0, 4.0, 3.0, 2.0, 1.0, 2.0, 3.0],
"sensor" => &["A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "C", "C", "C", "C", "C"],
}?;
println!("Multi-sensor DataFrame:");
println!("{}", multi_df);
let batch_processor = BatchProcessor::from_polars_df(
&multi_df,
"timestamp",
"reading",
"sensor",
)?;
let results = batch_processor.process_natural()?;
println!("\n✅ Processed {} time series", results.len());
println!(" Sensors: {:?}", results.keys());
for key in results.keys() {
if let Some(graph) = results.get(key) {
println!("\n🔹 Sensor {}:", key);
println!(" Nodes: {}", graph.node_count);
println!(" Edges: {}", graph.edges().len());
println!(" Avg Degree: {:.2}", graph.degree_sequence().iter().sum::<usize>() as f64 / graph.node_count as f64);
}
}
let results_df = results.to_polars_df()?;
println!("\n📊 Batch results as DataFrame:");
println!("{}", results_df);
println!("\n📊 Example 4: Complete Roundtrip");
println!("{}", "=".repeat(60));
let input_df = df! {
"t" => &[0.0, 1.0, 2.0, 3.0],
"y" => &[1.0, 4.0, 2.0, 3.0],
}?;
println!("1. Input DataFrame:");
println!("{}", input_df);
let ts = TimeSeries::<f64>::from_polars_df(&input_df, "t", "y")?;
println!("\n2. ✅ Converted to TimeSeries");
let g = VisibilityGraph::from_series(&ts).horizontal_visibility()?;
println!("3. ✅ Built Horizontal Visibility Graph");
let output_df = g.to_polars_df()?;
println!("\n4. Output DataFrame with graph properties:");
println!("{}", output_df);
println!("\n📊 Example 5: Lazy Evaluation (Efficient Pipeline)");
println!("{}", "=".repeat(60));
let lazy_df = df! {
"time" => &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0],
"value" => &[1.0, 3.0, 2.0, 4.0, 1.0, 3.0, 2.0, 4.0],
}?
.lazy()
.select([
col("time"),
col("value").alias("original_value"),
])
.collect()?;
println!("Processed DataFrame (lazy evaluation):");
println!("{}", lazy_df);
let lazy_series = TimeSeries::<f64>::from_polars_df(&lazy_df, "time", "original_value")?;
let lazy_graph = VisibilityGraph::from_series(&lazy_series).natural_visibility()?;
println!("\n✅ Graph from lazy DataFrame:");
println!(" Nodes: {}", lazy_graph.node_count);
println!(" Edges: {}", lazy_graph.edges().len());
println!("\n🎉 All Polars integration examples completed successfully!");
Ok(())
}
#[cfg(not(feature = "polars-integration"))]
fn main() {
eprintln!("❌ This example requires the 'polars-integration' feature.");
eprintln!("Run with: cargo run --example polars_integration --features polars-integration");
std::process::exit(1);
}