-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplot.rs
More file actions
124 lines (117 loc) · 3.39 KB
/
Copy pathplot.rs
File metadata and controls
124 lines (117 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! Interactive line-plot utility built on `egui`.
//!
//! This module provides a small native plotting helper for manual inspection of
//! numeric data. It opens an `eframe` window and renders one or more line
//! series in a native window.
//!
//! Use [`plot`] for a single series of `[x, y]` points, [`plot_indexed`] for a
//! single series of sampled values plotted against their indices, or
//! [`plot_series`] for multiple named series on the same plot.
//!
//! # Examples
//!
//! ```no_run
//! use utilities::plot;
//!
//! let mut data = Vec::with_capacity(100);
//! for i in 0..100 {
//! let x = i as f64 * 0.1;
//! data.push([x, x.sin()]);
//! }
//!
//! plot(&data);
//! ```
//!
//! ```no_run
//! use utilities::plot::plot_indexed;
//!
//! let mut data = Vec::with_capacity(100);
//! for i in 0..100 {
//! let x = i as f64 * 0.1;
//! data.push(x.sin());
//! }
//!
//! plot_indexed(&data);
//! ```
//!
//! ```no_run
//! use utilities::plot::plot_series;
//!
//! let mut sin = Vec::with_capacity(100);
//! let mut cos = Vec::with_capacity(100);
//! for i in 0..100 {
//! let x = i as f64 * 0.1;
//! sin.push([x, x.sin()]);
//! cos.push([x, x.cos()]);
//! }
//!
//! plot_series(&[("sin", &sin), ("cos", &cos)]);
//! ```
use eframe::egui;
use egui_plot::{Legend, Line, Plot, PlotPoints};
/// Render a single series in a native window, where each point is `[x, y]`.
pub fn plot(data: &[[f64; 2]]) {
let data = vec![Series {
name: String::new(),
points: data.to_vec(),
}];
eframe::run_native(
"plot",
eframe::NativeOptions::default(),
Box::new(|_| Ok(Box::new(PlotApp { data }))),
)
.expect("Failed to open plot window");
}
/// Render a single series of sampled values using the sample index as `x`.
pub fn plot_indexed(data: &[f64]) {
let mut points = Vec::with_capacity(data.len());
for (i, &y) in data.iter().enumerate() {
points.push([i as f64, y]);
}
plot(&points);
}
/// Render multiple named `[x, y]` series on the same plot.
pub fn plot_series(series: &[(&str, &[[f64; 2]])]) {
let mut data = Vec::with_capacity(series.len());
for (name, points) in series {
data.push(Series {
name: (*name).to_string(),
points: points.to_vec(),
});
}
eframe::run_native(
"plot",
eframe::NativeOptions::default(),
Box::new(|_| Ok(Box::new(PlotApp { data }))),
)
.expect("Failed to open plot window");
}
struct Series {
name: String,
points: Vec<[f64; 2]>,
}
struct PlotApp {
data: Vec<Series>,
}
impl eframe::App for PlotApp {
fn update(&mut self, ctx: &egui::Context, _: &mut eframe::Frame) {
if ctx.input(|i| i.key_pressed(egui::Key::Escape) || !i.keys_down.is_empty()) {
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
}
egui::CentralPanel::default().show(ctx, |ui| {
let mut plot = Plot::new("p");
if self.data.len() > 1 {
plot = plot.legend(Legend::default());
}
plot.show(ui, |pu| {
for series in &self.data {
let mut line = Line::new(PlotPoints::from_iter(series.points.iter().copied()));
if !series.name.is_empty() {
line = line.name(&series.name);
}
pu.line(line);
}
});
});
}
}