1use std::iter::{Fuse, FusedIterator};
7
8use super::*;
9
10pub mod bar;
11pub mod crop;
12pub mod output_zip;
13pub mod unwrapper;
14use marker::Area;
15
16pub mod marker;
17pub mod plotit;
18
19use plotit::*;
20use unwrapper::Unwrapper;
21
22#[derive(Copy, Clone, Debug)]
26pub enum PlotType {
27 Scatter,
28 Line,
29 Histo,
30 LineFill,
31 LineFillRaw,
32 Bars,
33}
34
35#[derive(Copy, Clone, Debug)]
39pub enum PlotMetaType {
40 Plot(PlotType),
41 Text,
42}
43
44#[derive(Copy, Clone)]
48pub enum ChainDisplay<A, B> {
49 A(A),
50 B(B),
51}
52impl<A: Display, B: Display> fmt::Display for ChainDisplay<A, B> {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 match self {
55 ChainDisplay::A(a) => write!(f, "{}", a),
56 ChainDisplay::B(b) => write!(f, "{}", b),
57 }
58 }
59}
60
61#[derive(Clone)]
65pub struct Chain<A, B> {
66 a: Fuse<A>,
67 b: Fuse<B>,
68}
69
70impl<L: Point, D1: Display, D2: Display, A, B> FusedIterator for Chain<A, B>
71where
72 A: Iterator<Item = PlotTag<L, D1>>,
73 B: Iterator<Item = PlotTag<L, D2>>,
74{
75}
76
77impl<L: Point, D1: Display, D2: Display, A, B> Iterator for Chain<A, B>
78where
79 A: Iterator<Item = PlotTag<L, D1>>,
80 B: Iterator<Item = PlotTag<L, D2>>,
81{
82 type Item = PlotTag<L, ChainDisplay<D1, D2>>;
83 fn size_hint(&self) -> (usize, Option<usize>) {
84 let (a, b) = self.a.size_hint();
85 let (c, d) = self.b.size_hint();
86
87 let k = match (b, d) {
88 (Some(a), Some(b)) => Some(a + b),
89 (Some(a), _) => Some(a),
90 (_, Some(b)) => Some(b),
91 (_, _) => None,
92 };
93 (a + c, k)
94 }
95 fn next(&mut self) -> Option<Self::Item> {
96 if let Some(a) = self.a.next() {
97 Some(match a {
98 PlotTag::Start {
99 name,
100 typ,
101 size_hint,
102 } => PlotTag::Start {
103 name: ChainDisplay::A(name),
104 typ,
105 size_hint,
106 },
107 PlotTag::Plot(p) => PlotTag::Plot(p),
108 PlotTag::Finish() => PlotTag::Finish(),
109 })
110 } else {
111 self.b.next().map(|a| match a {
112 PlotTag::Start {
113 name,
114 typ,
115 size_hint,
116 } => PlotTag::Start {
117 name: ChainDisplay::B(name),
118 typ,
119 size_hint,
120 },
121 PlotTag::Plot(p) => PlotTag::Plot(p),
122 PlotTag::Finish() => PlotTag::Finish(),
123 })
124 }
125 }
126}
127
128pub trait PlotIterator {
178 type L: Point;
179 type P: Iterator<Item = PlotTag<Self::L, Self::D>>;
180 type D: Display;
181 fn unpack(self) -> PlotRes<Self::P, Self::L>;
182
183 fn chain<P: PlotIterator<L = Self::L>>(self, other: P) -> PlotRes<Chain<Self::P, P::P>, Self::L>
184 where
185 Self: Sized,
186 {
187 let PlotRes {
188 area: curr_area,
189 it: p1,
190 num_plots: n1,
191 } = self.unpack();
192 let PlotRes {
193 area: other_area,
194 it: p,
195 num_plots: n2,
196 } = other.unpack();
197 let mut area = curr_area;
198 area.grow_area(&other_area);
199 PlotRes {
200 area,
201 it: Chain {
202 a: p1.fuse(),
203 b: p.fuse(),
204 },
205 num_plots: n1 + n2,
206 }
207 }
208
209 fn dyn_box<'a>(self) -> PlotRes<DynIt<'a, Self::L, Self::D>, Self::L>
210 where
211 Self::P: 'a,
212 Self: Sized,
213 {
214 let PlotRes {
215 area,
216 it,
217 num_plots,
218 } = self.unpack();
219 PlotRes {
220 it: Box::new(it),
221 area,
222 num_plots,
223 }
224 }
225}
226
227type DynIt<'a, L, D> = Box<dyn Iterator<Item = PlotTag<L, D>> + 'a>;
228
229#[derive(Copy, Clone)]
230pub struct PlotRes<I: Iterator, L: Point> {
231 pub(crate) area: Area<L::X, L::Y>,
232 pub(crate) num_plots: usize,
233 pub(crate) it: I,
234}
235
236impl<P: Iterator<Item = PlotTag<L, D>>, L: Point, D: Display> PlotIterator for PlotRes<P, L> {
237 type L = L;
238 type P = P;
239 type D = D;
240
241 fn unpack(self) -> PlotRes<Self::P, Self::L> {
242 self
243 }
244}
245
246pub trait Point {
247 type X: PlotNum;
248 type Y: PlotNum;
249 fn get(&self) -> (&Self::X, &Self::Y);
250}
251impl<X: PlotNum, Y: PlotNum> Point for (X, Y) {
252 type X = X;
253 type Y = Y;
254
255 fn get(&self) -> (&Self::X, &Self::Y) {
256 (&self.0, &self.1)
257 }
258}
259
260#[derive(Clone)]
261pub enum PlotTag<L: Point, D: Display> {
262 Start {
263 name: D,
264 typ: PlotMetaType,
265 size_hint: (usize, Option<usize>),
266 },
267 Plot(L),
268 Finish(),
269}
270
271pub fn origin<L: Point>() -> PlotRes<std::iter::Empty<PlotTag<L, &'static str>>, L>
275where
276 L::X: HasZero,
277 L::Y: HasZero,
278{
279 markers(Some(L::X::zero()), Some(L::Y::zero()))
280}
281
282pub fn markers<XI: IntoIterator<Item = L::X>, YI: IntoIterator<Item = L::Y>, L: Point>(
286 x: XI,
287 y: YI,
288) -> PlotRes<std::iter::Empty<PlotTag<L, &'static str>>, L> {
289 let mut area = Area::new();
290 for a in x {
291 area.grow(Some(&a), None);
292 }
293 for a in y {
294 area.grow(None, Some(&a));
295 }
296
297 PlotRes {
298 area,
299 it: std::iter::empty(),
300 num_plots: 0,
301 }
302}
303
304pub fn cloned<L: Point, I: IntoIterator>(it: I) -> ClonedPlotIt<I::IntoIter>
308where
309 I::IntoIter: Clone,
310 I::Item: build::unwrapper::Unwrapper<Item = L>,
311{
312 ClonedPlotIt::new(it.into_iter())
313}
314
315pub struct SinglePlotBuilder<D> {
343 label: D,
344}
345
346#[derive(Clone)]
347pub struct PlotIterCreator<I, D> {
348 start: Option<(PlotMetaType, D)>,
349 it: Fuse<I>,
350 posted_finish: bool,
351}
352impl<I: Iterator<Item = L>, L: Point, D: Display> PlotIterCreator<I, D> {
353 fn new(label: D, typ: PlotMetaType, it: I) -> Self {
354 Self {
355 start: Some((typ, label)),
356 it: it.fuse(),
357 posted_finish: false,
358 }
359 }
360}
361
362impl<I: ExactSizeIterator<Item = L>, L: Point, D: Display> ExactSizeIterator
363 for PlotIterCreator<I, D>
364{
365}
366impl<I: Iterator<Item = L>, L: Point, D: Display> FusedIterator for PlotIterCreator<I, D> {}
367impl<I: Iterator<Item = L>, L: Point, D: Display> Iterator for PlotIterCreator<I, D> {
368 type Item = PlotTag<L, D>;
369 fn next(&mut self) -> Option<PlotTag<L, D>> {
370 if let Some((typ, name)) = self.start.take() {
371 Some(PlotTag::Start {
372 typ,
373 name,
374 size_hint: self.size_hint(),
375 })
376 } else if let Some(l) = self.it.next() {
377 Some(PlotTag::Plot(l))
378 } else if !self.posted_finish {
379 self.posted_finish = true;
380 Some(PlotTag::Finish())
381 } else {
382 None
383 }
384 }
385 fn size_hint(&self) -> (usize, Option<usize>) {
386 let (a, b) = self.it.size_hint();
387 (a + 2, b.map(|b| b + 2))
388 }
389}
390
391impl<D: Display> SinglePlotBuilder<D> {
392 fn gen<P: PlotIt>(self, it: P, typ: PlotMetaType) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
393 let mut area = Area::new();
394 let it = it.unpack(&mut area);
395
396 PlotRes {
397 area,
398 it: PlotIterCreator::new(self.label, typ, it),
399 num_plots: 1,
400 }
401 }
402 pub fn line<P: PlotIt>(self, it: P) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
406 self.gen(it, PlotMetaType::Plot(PlotType::Line))
407 }
408
409 pub(crate) fn bars<P: PlotIt>(self, it: P) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
410 self.gen(it, PlotMetaType::Plot(PlotType::Bars))
411 }
412
413 pub fn scatter<P: PlotIt>(self, it: P) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
418 self.gen(it, PlotMetaType::Plot(PlotType::Scatter))
419 }
420
421 pub fn histogram<P: PlotIt>(self, it: P) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
425 self.gen(it, PlotMetaType::Plot(PlotType::Histo))
426 }
427
428 pub fn line_fill<P: PlotIt>(self, it: P) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
431 self.gen(it, PlotMetaType::Plot(PlotType::LineFill))
432 }
433
434 pub fn line_fill_raw<P: PlotIt>(self, it: P) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
438 self.gen(it, PlotMetaType::Plot(PlotType::LineFillRaw))
439 }
440
441 pub fn text<L: Point>(self) -> PlotRes<PlotIterCreator<std::iter::Empty<L>, D>, L> {
445 let area = Area::new();
446 PlotRes {
447 area,
448 it: PlotIterCreator::new(self.label, PlotMetaType::Text, std::iter::empty()),
449 num_plots: 1,
450 }
451 }
452}
453
454pub fn plot<D: Display>(label: D) -> SinglePlotBuilder<D> {
458 SinglePlotBuilder { label }
459}
460
461impl<I: IntoIterator<Item = P>, P: PlotIterator<L = L>, L: Point> PlotIterator for I {
462 type L = L;
463 type P = std::iter::Flatten<std::vec::IntoIter<P::P>>;
464 type D = P::D;
465 fn unpack(self) -> PlotRes<Self::P, Self::L> {
466 let mut total = 0;
467 let (areas, its): (Vec<_>, Vec<_>) = self
468 .into_iter()
469 .map(|x| {
470 let PlotRes {
471 area,
472 it,
473 num_plots,
474 } = x.unpack();
475 total += num_plots;
476 (area, it)
477 })
478 .unzip();
479
480 let mut area = Area::new();
481 for a in areas {
482 area.grow_area(&a);
483 }
484
485 let it = its.into_iter().flatten();
486
487 PlotRes {
488 area,
489 it,
490 num_plots: total,
491 }
492 }
493}