You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Thanks for putting this together, outputting a SVG is a great fit for my CLI app, so looking forward to trying this out some more.
I've been experimenting using this package to plot some "real" data, and some of it is a little boring, including a series with only a single value, but unfortunately this panics on the 0.3.0 tag since the default axis calculation needs at least two different values in the series.
With
[dependencies]
plotlib= { git = "https://github.com/milliams/plotlib", tag = "0.3.0" }
a cut down version of the example in the readme, with a single value in data1:
extern crate plotlib;
use plotlib::scatter::Scatter;
use plotlib::scatter;
use plotlib::style::{Marker, Point};
use plotlib::view::View;
use plotlib::page::Page;
fn main() {
// Scatter plots expect a list of pairs
let data1 = [(-3.0, 2.3)];
// We create our scatter plot from the data
let s1 = Scatter::from_vec(&data1)
.style(scatter::Style::new()
.marker(Marker::Square) // setting the marker to be a square
.colour("#DD3355")); // and a custom colour
// The 'view' describes what set of data is drawn
let v = View::new()
.add(&s1)
.x_range(-5., 10.)
.y_range(-2., 6.)
.x_label("Some varying variable")
.y_label("The response of something");
// A page with a single view is then saved to an SVG file
Page::single(&v).save("scatter.svg");
}
produces this error at runtime:
thread 'main' panicked at 'assertion failed: lower < upper', D:\rust\cargo\git\checkouts\plotlib-407c626431dc1ac2\8ed7480\src\axis.rs:15:9
stack backtrace:
0: std::sys::windows::backtrace::unwind_backtrace
at C:\projects\rust\src\libstd\sys\windows\backtrace\mod.rs:65
1: std::sys_common::backtrace::_print
at C:\projects\rust\src\libstd\sys_common\backtrace.rs:71
2: std::sys_common::backtrace::print
at C:\projects\rust\src\libstd\sys_common\backtrace.rs:59
3: std::panicking::default_hook::{{closure}}
at C:\projects\rust\src\libstd\panicking.rs:211
4: std::panicking::default_hook
at C:\projects\rust\src\libstd\panicking.rs:227
5: std::panicking::rust_panic_with_hook
at C:\projects\rust\src\libstd\panicking.rs:463
6: std::panicking::begin_panic<str*>
at C:\projects\rust\src\libstd\panicking.rs:397
7: plotlib::axis::Range::new
at D:\rust\cargo\git\checkouts\plotlib-407c626431dc1ac2\8ed7480\src\axis.rs:15
8: plotlib::view::View::default_x_range
at D:\rust\cargo\git\checkouts\plotlib-407c626431dc1ac2\8ed7480\src\view.rs:88
9: plotlib::view::View::create_axes
at D:\rust\cargo\git\checkouts\plotlib-407c626431dc1ac2\8ed7480\src\view.rs:103
10: plotlib::view::View::to_svg
at D:\rust\cargo\git\checkouts\plotlib-407c626431dc1ac2\8ed7480\src\view.rs:127
11: plotlib::page::Page::to_svg
at D:\rust\cargo\git\checkouts\plotlib-407c626431dc1ac2\8ed7480\src\page.rs:40
12: plotlib::page::Page::save<str*>
at D:\rust\cargo\git\checkouts\plotlib-407c626431dc1ac2\8ed7480\src\page.rs:68
13: plot_test::main
at .\src\main.rs:27
14: std::rt::lang_start::{{closure}}<()>
at C:\projects\rust\src\libstd\rt.rs:74
15: std::rt::lang_start_internal::{{closure}}
at C:\projects\rust\src\libstd\rt.rs:59
16: std::panicking::try::do_call<closure,i32>
at C:\projects\rust\src\libstd\panicking.rs:310
17: panic_unwind::__rust_maybe_catch_panic
at C:\projects\rust\src\libpanic_unwind\lib.rs:105
18: std::panicking::try
at C:\projects\rust\src\libstd\panicking.rs:289
19: std::panic::catch_unwind
at C:\projects\rust\src\libstd\panic.rs:374
20: std::rt::lang_start_internal
at C:\projects\rust\src\libstd\rt.rs:58
21: std::rt::lang_start<()>
at C:\projects\rust\src\libstd\rt.rs:74
22: main
23: invoke_main
at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:78
24: __scrt_common_main_seh
at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:283
25: BaseThreadInitThunk
26: RtlUserThreadStart
error: process didn't exit successfully: `target\debug\plot_test.exe` (exit code: 101)
It looks like the problem is that when there is a single data point, x_range in scatter.ts,
fn x_range(&self) -> (f64, f64) {
let mut min = f64::INFINITY;
let mut max = f64::NEG_INFINITY;
for &(x, _) in &self.data {
min = min.min(x);
max = max.max(x);
}
(min, max)
}
returns the same value for min and max, so the assert!(lower < upper); fails.
It also fails if there are no entries in self.data, since it will leave lower as f64::INFINITY and upper as f64::NEG_INFINITY.
I'm just getting started with Rust, but a pattern that I've seen in other code is to use a fold to produce values when the collection may be empty:
That could be a fix for the no entries situation, for a single entry the assert probably needs to be relaxed, or the caller could define a default range of say min to min + 1 if min == max.
The text was updated successfully, but these errors were encountered:
DouglasLivingstone
changed the title
Cannot plot series with a zero or one value
Cannot plot series with zero or one values
Jul 15, 2018
Indeed that is a case that is not handled very well yet. I general I need to develop a proper error handling solution for plotlib. Likely this will use something like failure.
In the short term, I think that in the case you showed above, if you explicitly specified the x and y range then it shouldn't need to check the ranges of the data set and so shouldn't matter about the number of data points.
Also, it should definitely work for a single-valued data set as we can special-case it to set the min and max to the same value.
For the zero-length data set, we could filter those out at the view level and ignore them when plotting.
simonrw
added a commit
to simonrw/plotlib
that referenced
this issue
Jul 19, 2018
This is only a partial implementation, driven by milliams#7. Instead of
asserting, we return an error with a (hopefully) helpful error message.
The error types are then propagated through the call stack, using
`context` where possible to add more information.
Thanks for putting this together, outputting a SVG is a great fit for my CLI app, so looking forward to trying this out some more.
I've been experimenting using this package to plot some "real" data, and some of it is a little boring, including a series with only a single value, but unfortunately this panics on the
0.3.0
tag since the default axis calculation needs at least two different values in the series.With
a cut down version of the example in the readme, with a single value in
data1
:produces this error at runtime:
It looks like the problem is that when there is a single data point,
x_range
inscatter.ts
,returns the same value for
min
andmax
, so theassert!(lower < upper);
fails.It also fails if there are no entries in
self.data
, since it will leavelower
asf64::INFINITY
andupper
asf64::NEG_INFINITY
.I'm just getting started with Rust, but a pattern that I've seen in other code is to use a fold to produce values when the collection may be empty:
That could be a fix for the no entries situation, for a single entry the assert probably needs to be relaxed, or the caller could define a default range of say
min
tomin + 1
ifmin == max
.The text was updated successfully, but these errors were encountered: