1use serde_json::{ Number, Value };
22use crate::core::{
23 Matplotlib,
24 MatplotlibOpts,
25 Opt,
26 GSPos,
27 PyValue,
28 AsPy,
29};
30
31pub trait Real {
34 fn into_f64(self) -> f64;
36}
37
38impl Real for f64 { fn into_f64(self) -> f64 { self } }
39impl Real for &f64 { fn into_f64(self) -> f64 { *self } }
40
41macro_rules! impl_real {
42 ( $t:ty { into } ) => {
43 impl Real for $t { fn into_f64(self) -> f64 { self.into() } }
44 };
45 ( { * } $t:ty { into } ) => {
46 impl Real for $t { fn into_f64(self) -> f64 { (*self).into() } }
47 };
48 ( $t:ty { as } ) => {
49 impl Real for $t { fn into_f64(self) -> f64 { self as f64 } }
50 };
51 ( { * } $t:ty { as } ) => {
52 impl Real for $t { fn into_f64(self) -> f64 { *self as f64 } }
53 };
54}
55impl_real!(f32 { into });
56impl_real!({ * } &f32 { into });
57impl_real!(u8 { into });
58impl_real!({ * } &u8 { into });
59impl_real!(u16 { into });
60impl_real!({ * } &u16 { into });
61impl_real!(u32 { into });
62impl_real!({ * } &u32 { into });
63impl_real!(u64 { as });
64impl_real!({ * } &u64 { as });
65impl_real!(u128 { as });
66impl_real!({ * } &u128 { as });
67impl_real!(usize { as });
68impl_real!({ * } &usize { as });
69impl_real!(i8 { into });
70impl_real!({ * } &i8 { into });
71impl_real!(i16 { into });
72impl_real!({ * } &i16 { into });
73impl_real!(i32 { into });
74impl_real!({ * } &i32 { into });
75impl_real!(i64 { as });
76impl_real!({ * } &i64 { as });
77impl_real!(i128 { as });
78impl_real!({ * } &i128 { as });
79impl_real!(isize { as });
80impl_real!({ * } &isize { as });
81
82#[derive(Clone, Debug, PartialEq, Eq)]
90pub struct Raw(pub String);
91
92impl Raw {
93 pub fn new(s: &str) -> Self { Self(s.into()) }
95}
96
97pub fn raw(s: &str) -> Raw { Raw::new(s) }
99
100impl Matplotlib for Raw {
101 fn is_prelude(&self) -> bool { false }
102
103 fn data(&self) -> Option<Value> { None }
104
105 fn py_cmd(&self) -> String { self.0.clone() }
106}
107
108#[derive(Clone, Debug, PartialEq, Eq)]
116pub struct Prelude(pub String);
117
118impl Prelude {
119 pub fn new(s: &str) -> Self { Self(s.into()) }
121}
122
123pub fn prelude(s: &str) -> Prelude { Prelude::new(s) }
125
126impl Matplotlib for Prelude {
127 fn is_prelude(&self) -> bool { true }
128
129 fn data(&self) -> Option<Value> { None }
130
131 fn py_cmd(&self) -> String { self.0.clone() }
132}
133
134#[derive(Clone, Debug, PartialEq, Eq)]
144pub struct Backend(pub String);
145
146impl Backend {
147 pub fn new(backend: &str) -> Self { Self(backend.into()) }
149}
150
151pub fn backend(backend: &str) -> Backend { Backend::new(backend) }
153
154impl Matplotlib for Backend {
155 fn is_prelude(&self) -> bool { true }
156
157 fn data(&self) -> Option<Value> { None }
158
159 fn py_cmd(&self) -> String {
160 format!("matplotlib.use({})", self.0.as_py())
161 }
162}
163
164#[derive(Clone, Debug, PartialEq, Eq)]
174pub struct CloseFig(pub String);
175
176impl CloseFig {
177 pub fn new(fig: &str) -> Self { Self(fig.into()) }
179}
180
181pub fn close_fig(fig: &str) -> CloseFig { CloseFig::new(fig) }
183
184impl Matplotlib for CloseFig {
185 fn is_prelude(&self) -> bool { false }
186
187 fn data(&self) -> Option<Value> { None }
188
189 fn py_cmd(&self) -> String {
190 format!("plt.close({})", self.0)
191 }
192}
193
194#[derive(Clone, Debug, PartialEq, Default)]
208pub struct Init3D {
209 pub opts: Vec<Opt>,
211}
212
213impl Init3D {
214 pub fn new() -> Self { Self { opts: Vec::new() } }
216}
217
218impl Matplotlib for Init3D {
219 fn is_prelude(&self) -> bool { false }
220
221 fn data(&self) -> Option<Value> { None }
222
223 fn py_cmd(&self) -> String {
224 format!("\
225 fig = plt.figure()\n\
226 ax = axes3d.Axes3D(fig, auto_add_to_figure=False{}{})\n\
227 fig.add_axes(ax)",
228 if self.opts.is_empty() { "" } else { ", " },
229 self.opts.as_py(),
230 )
231 }
232}
233
234impl MatplotlibOpts for Init3D {
235 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
236 self.opts.push((key, val).into());
237 self
238 }
239}
240
241#[derive(Clone, Debug, PartialEq)]
257pub struct InitGrid {
258 pub nrows: usize,
260 pub ncols: usize,
262 pub opts: Vec<Opt>,
264}
265
266impl InitGrid {
267 pub fn new(nrows: usize, ncols: usize) -> Self {
269 Self { nrows, ncols, opts: Vec::new() }
270 }
271}
272
273pub fn init_grid(nrows: usize, ncols: usize) -> InitGrid {
275 InitGrid::new(nrows, ncols)
276}
277
278impl Matplotlib for InitGrid {
279 fn is_prelude(&self) -> bool { false }
280
281 fn data(&self) -> Option<Value> { None }
282
283 fn py_cmd(&self) -> String {
284 format!("\
285 fig, AX = plt.subplots(nrows={}, ncols={}{}{})\n\
286 AX = AX.reshape(({}, {}))\n\
287 ax = AX[0, 0]",
288 self.nrows,
289 self.ncols,
290 if self.opts.is_empty() { "" } else { ", " },
291 self.opts.as_py(),
292 self.nrows,
293 self.ncols,
294 )
295 }
296}
297
298impl MatplotlibOpts for InitGrid {
299 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
300 self.opts.push((key, val).into());
301 self
302 }
303}
304
305#[derive(Clone, Debug, PartialEq)]
327pub struct InitGridSpec {
328 pub gridspec_kw: Vec<Opt>,
330 pub positions: Vec<GSPos>,
332}
333
334impl InitGridSpec {
335 pub fn new<I, P>(gridspec_kw: I, positions: P) -> Self
337 where
338 I: IntoIterator<Item = Opt>,
339 P: IntoIterator<Item = GSPos>,
340 {
341 Self {
342 gridspec_kw: gridspec_kw.into_iter().collect(),
343 positions: positions.into_iter().collect(),
344 }
345 }
346}
347
348pub fn init_gridspec<I, P>(gridspec_kw: I, positions: P) -> InitGridSpec
350where
351 I: IntoIterator<Item = Opt>,
352 P: IntoIterator<Item = GSPos>,
353{
354 InitGridSpec::new(gridspec_kw, positions)
355}
356
357impl Matplotlib for InitGridSpec {
358 fn is_prelude(&self) -> bool { false }
359
360 fn data(&self) -> Option<Value> { None }
361
362 fn py_cmd(&self) -> String {
363 let mut code =
364 format!("\
365 fig = plt.figure()\n\
366 gs = fig.add_gridspec({})\n\
367 AX = np.array([\n",
368 self.gridspec_kw.as_py(),
369 );
370 for GSPos { i, j, sharex: _, sharey: _ } in self.positions.iter() {
371 code.push_str(
372 &format!(" fig.add_subplot(gs[{}:{}, {}:{}]),\n",
373 i.start, i.end, j.start, j.end,
374 )
375 );
376 }
377 code.push_str("])\n");
378 let iter = self.positions.iter().enumerate();
379 for (k, GSPos { i: _, j: _, sharex, sharey }) in iter {
380 if let Some(x) = sharex {
381 code.push_str(&format!("AX[{}].sharex(AX[{}])\n", k, x));
382 }
383 if let Some(y) = sharey {
384 code.push_str(&format!("AX[{}].sharey(AX[{}])\n", k, y));
385 }
386 }
387 code.push_str("ax = AX[0]\n");
388 code
389 }
390}
391
392impl MatplotlibOpts for InitGridSpec {
393 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
394 self.gridspec_kw.push((key, val).into());
395 self
396 }
397}
398
399#[derive(Clone, Debug, PartialEq)]
413pub struct RcParam {
414 pub key: String,
416 pub val: PyValue,
418}
419
420impl RcParam {
421 pub fn new<T: Into<PyValue>>(key: &str, val: T) -> Self {
423 Self { key: key.into(), val: val.into() }
424 }
425}
426
427pub fn rcparam<T: Into<PyValue>>(key: &str, val: T) -> RcParam {
429 RcParam::new(key, val)
430}
431
432impl Matplotlib for RcParam {
433 fn is_prelude(&self) -> bool { true }
434
435 fn data(&self) -> Option<Value> { None }
436
437 fn py_cmd(&self) -> String {
438 format!("plt.rcParams[{}] = {}", self.key.as_py(), self.val.as_py())
439 }
440}
441
442#[derive(Copy, Clone, Debug, PartialEq, Eq)]
452pub struct TeX(pub bool);
453
454impl TeX {
455 pub fn on() -> Self { Self(true) }
457
458 pub fn off() -> Self { Self(false) }
460}
461
462pub fn tex_on() -> TeX { TeX(true) }
464
465pub fn tex_off() -> TeX { TeX(false) }
467
468impl Matplotlib for TeX {
469 fn is_prelude(&self) -> bool { true }
470
471 fn data(&self) -> Option<Value> { None }
472
473 fn py_cmd(&self) -> String {
474 format!("plt.rcParams[\"text.usetex\"] = {}", self.0.as_py())
475 }
476}
477
478#[derive(Clone, Debug, PartialEq, Eq)]
488pub struct FocusAx(pub String);
489
490impl FocusAx {
491 pub fn new(expr: &str) -> Self { Self(expr.into()) }
493}
494
495pub fn focus_ax(expr: &str) -> FocusAx { FocusAx::new(expr) }
497
498impl Matplotlib for FocusAx {
499 fn is_prelude(&self) -> bool { false }
500
501 fn data(&self) -> Option<Value> { None }
502
503 fn py_cmd(&self) -> String { format!("ax = {}", self.0) }
504}
505
506#[derive(Clone, Debug, PartialEq, Eq)]
516pub struct FocusFig(pub String);
517
518impl FocusFig {
519 pub fn new(expr: &str) -> Self { Self(expr.into()) }
521}
522
523pub fn focus_fig(expr: &str) -> FocusFig { FocusFig::new(expr) }
525
526impl Matplotlib for FocusFig {
527 fn is_prelude(&self) -> bool { false }
528
529 fn data(&self) -> Option<Value> { None }
530
531 fn py_cmd(&self) -> String { format!("fig = {}", self.0) }
532}
533
534#[derive(Clone, Debug, PartialEq, Eq)]
544pub struct FocusCBar(pub String);
545
546impl FocusCBar {
547 pub fn new(expr: &str) -> Self { Self(expr.into()) }
549}
550
551pub fn focus_cbar(expr: &str) -> FocusCBar { FocusCBar::new(expr) }
553
554impl Matplotlib for FocusCBar {
555 fn is_prelude(&self) -> bool { false }
556
557 fn data(&self) -> Option<Value> { None }
558
559 fn py_cmd(&self) -> String { format!("cbar = {}", self.0) }
560}
561
562#[derive(Clone, Debug, PartialEq, Eq)]
572pub struct FocusIm(pub String);
573
574impl FocusIm {
575 pub fn new(expr: &str) -> Self { Self(expr.into()) }
577}
578
579pub fn focus_im(expr: &str) -> FocusIm { FocusIm::new(expr) }
581
582impl Matplotlib for FocusIm {
583 fn is_prelude(&self) -> bool { false }
584
585 fn data(&self) -> Option<Value> { None }
586
587 fn py_cmd(&self) -> String { format!("im = {}", self.0) }
588}
589
590#[derive(Clone, Debug, PartialEq)]
600pub struct Plot {
601 pub x: Vec<f64>,
603 pub y: Vec<f64>,
605 pub opts: Vec<Opt>,
607}
608
609impl Plot {
610 pub fn new<X, XE, Y, YE>(x: X, y: Y) -> Self
612 where
613 X: IntoIterator<Item = XE>,
614 XE: Real,
615 Y: IntoIterator<Item = YE>,
616 YE: Real,
617 {
618 Self {
619 x: x.into_iter().map(Real::into_f64).collect(),
620 y: y.into_iter().map(Real::into_f64).collect(),
621 opts: Vec::new(),
622 }
623 }
624
625 pub fn new_pairs<I, XE, YE>(data: I) -> Self
627 where
628 I: IntoIterator<Item = (XE, YE)>,
629 XE: Real,
630 YE: Real,
631 {
632 let (x, y): (Vec<f64>, Vec<f64>) =
633 data.into_iter()
634 .map(|(x, y)| (x.into_f64(), y.into_f64()))
635 .unzip();
636 Self { x, y, opts: Vec::new() }
637 }
638}
639
640pub fn plot<X, XE, Y, YE>(x: X, y: Y) -> Plot
642where
643 X: IntoIterator<Item = XE>,
644 XE: Real,
645 Y: IntoIterator<Item = YE>,
646 YE: Real,
647{
648 Plot::new(x, y)
649}
650
651pub fn plot_pairs<I, XE, YE>(data: I) -> Plot
653where
654 I: IntoIterator<Item = (XE, YE)>,
655 XE: Real,
656 YE: Real,
657{
658 Plot::new_pairs(data)
659}
660
661impl Matplotlib for Plot {
662 fn is_prelude(&self) -> bool { false }
663
664 fn data(&self) -> Option<Value> {
665 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
666 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
667 Some(Value::Array(vec![x.into(), y.into()]))
668 }
669
670 fn py_cmd(&self) -> String {
671 format!("ax.plot(data[0], data[1]{}{})",
672 if self.opts.is_empty() { "" } else { ", " },
673 self.opts.as_py(),
674 )
675 }
676}
677
678impl MatplotlibOpts for Plot {
679 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
680 self.opts.push((key, val).into());
681 self
682 }
683}
684
685#[derive(Clone, Debug, PartialEq)]
695pub struct Hist {
696 pub data: Vec<f64>,
698 pub opts: Vec<Opt>,
700}
701
702impl Hist {
703 pub fn new<I, E>(data: I) -> Self
705 where
706 I: IntoIterator<Item = E>,
707 E: Real,
708 {
709 let data: Vec<f64> = data.into_iter().map(Real::into_f64).collect();
710 Self { data, opts: Vec::new() }
711 }
712}
713
714pub fn hist<I, E>(data: I) -> Hist
716where
717 I: IntoIterator<Item = E>,
718 E: Real,
719{
720 Hist::new(data)
721}
722
723impl Matplotlib for Hist {
724 fn is_prelude(&self) -> bool { false }
725
726 fn data(&self) -> Option<Value> {
727 let data: Vec<Value> =
728 self.data.iter().copied().map(Value::from).collect();
729 Some(Value::Array(data))
730 }
731
732 fn py_cmd(&self) -> String {
733 format!("ax.hist(data{}{})",
734 if self.opts.is_empty() { "" } else { ", " },
735 self.opts.as_py(),
736 )
737 }
738}
739
740impl MatplotlibOpts for Hist {
741 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
742 self.opts.push((key, val).into());
743 self
744 }
745}
746
747#[derive(Clone, Debug, PartialEq)]
757pub struct Hist2d {
758 pub x: Vec<f64>,
760 pub y: Vec<f64>,
762 pub opts: Vec<Opt>,
764}
765
766impl Hist2d {
767 pub fn new<X, XE, Y, YE>(x: X, y: Y) -> Self
769 where
770 X: IntoIterator<Item = XE>,
771 XE: Real,
772 Y: IntoIterator<Item = YE>,
773 YE: Real,
774 {
775 let x: Vec<f64> = x.into_iter().map(Real::into_f64).collect();
776 let y: Vec<f64> = y.into_iter().map(Real::into_f64).collect();
777 Self { x, y, opts: Vec::new() }
778 }
779
780 pub fn new_pairs<I, XE, YE>(data: I) -> Self
782 where
783 I: IntoIterator<Item = (XE, YE)>,
784 XE: Real,
785 YE: Real,
786 {
787 let (x, y): (Vec<f64>, Vec<f64>) =
788 data.into_iter()
789 .map(|(x, y)| (x.into_f64(), y.into_f64()))
790 .unzip();
791 Self { x, y, opts: Vec::new() }
792 }
793}
794
795pub fn hist2d<X, XE, Y, YE>(x: X, y: Y) -> Hist2d
797where
798 X: IntoIterator<Item = XE>,
799 XE: Real,
800 Y: IntoIterator<Item = YE>,
801 YE: Real,
802{
803 Hist2d::new(x, y)
804}
805
806pub fn hist2d_pairs<I, XE, YE>(data: I) -> Hist2d
808where
809 I: IntoIterator<Item = (XE, YE)>,
810 XE: Real,
811 YE: Real,
812{
813 Hist2d::new_pairs(data)
814}
815
816impl Matplotlib for Hist2d {
817 fn is_prelude(&self) -> bool { false }
818
819 fn data(&self) -> Option<Value> {
820 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
821 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
822 Some(Value::Array(vec![x.into(), y.into()]))
823 }
824
825 fn py_cmd(&self) -> String {
826 format!("ax.hist2d(data[0], data[1]{}{})",
827 if self.opts.is_empty() { "" } else { ", " },
828 self.opts.as_py(),
829 )
830 }
831}
832
833impl MatplotlibOpts for Hist2d {
834 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
835 self.opts.push((key, val).into());
836 self
837 }
838}
839
840#[derive(Clone, Debug, PartialEq)]
850pub struct Scatter {
851 pub x: Vec<f64>,
853 pub y: Vec<f64>,
855 pub opts: Vec<Opt>,
857}
858
859impl Scatter {
860 pub fn new<X, XE, Y, YE>(x: X, y: Y) -> Self
862 where
863 X: IntoIterator<Item = XE>,
864 XE: Real,
865 Y: IntoIterator<Item = YE>,
866 YE: Real,
867 {
868 Self {
869 x: x.into_iter().map(Real::into_f64).collect(),
870 y: y.into_iter().map(Real::into_f64).collect(),
871 opts: Vec::new(),
872 }
873 }
874
875 pub fn new_pairs<I, XE, YE>(data: I) -> Self
877 where
878 I: IntoIterator<Item = (XE, YE)>,
879 XE: Real,
880 YE: Real,
881 {
882 let (x, y): (Vec<f64>, Vec<f64>) =
883 data.into_iter()
884 .map(|(x, y)| (x.into_f64(), y.into_f64()))
885 .unzip();
886 Self { x, y, opts: Vec::new() }
887 }
888}
889
890pub fn scatter<X, XE, Y, YE>(x: X, y: Y) -> Scatter
892where
893 X: IntoIterator<Item = XE>,
894 XE: Real,
895 Y: IntoIterator<Item = YE>,
896 YE: Real,
897{
898 Scatter::new(x, y)
899}
900
901pub fn scatter_pairs<I, XE, YE>(data: I) -> Scatter
903where
904 I: IntoIterator<Item = (XE, YE)>,
905 XE: Real,
906 YE: Real,
907{
908 Scatter::new_pairs(data)
909}
910
911impl Matplotlib for Scatter {
912 fn is_prelude(&self) -> bool { false }
913
914 fn data(&self) -> Option<Value> {
915 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
916 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
917 Some(Value::Array(vec![x.into(), y.into()]))
918 }
919
920 fn py_cmd(&self) -> String {
921 format!("ax.scatter(data[0], data[1]{}{})",
922 if self.opts.is_empty() { "" } else { ", " },
923 self.opts.as_py(),
924 )
925 }
926}
927
928impl MatplotlibOpts for Scatter {
929 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
930 self.opts.push((key, val).into());
931 self
932 }
933}
934
935#[derive(Clone, Debug, PartialEq)]
945pub struct Stem {
946 pub x: Vec<f64>,
948 pub y: Vec<f64>,
950 pub opts: Vec<Opt>,
952}
953
954impl Stem {
955 pub fn new<X, XE, Y, YE>(x: X, y: Y) -> Self
957 where
958 X: IntoIterator<Item = XE>,
959 XE: Real,
960 Y: IntoIterator<Item = YE>,
961 YE: Real,
962 {
963 Self {
964 x: x.into_iter().map(Real::into_f64).collect(),
965 y: y.into_iter().map(Real::into_f64).collect(),
966 opts: Vec::new(),
967 }
968 }
969
970 pub fn new_pairs<I, XE, YE>(data: I) -> Self
972 where
973 I: IntoIterator<Item = (XE, YE)>,
974 XE: Real,
975 YE: Real,
976 {
977 let (x, y): (Vec<f64>, Vec<f64>) =
978 data.into_iter()
979 .map(|(x, y)| (x.into_f64(), y.into_f64()))
980 .unzip();
981 Self { x, y, opts: Vec::new() }
982 }
983}
984
985pub fn stem<X, XE, Y, YE>(x: X, y: Y) -> Stem
987where
988 X: IntoIterator<Item = XE>,
989 XE: Real,
990 Y: IntoIterator<Item = YE>,
991 YE: Real,
992{
993 Stem::new(x, y)
994}
995
996pub fn stem_pairs<I, XE, YE>(data: I) -> Stem
998where
999 I: IntoIterator<Item = (XE, YE)>,
1000 XE: Real,
1001 YE: Real,
1002{
1003 Stem::new_pairs(data)
1004}
1005
1006impl Matplotlib for Stem {
1007 fn is_prelude(&self) -> bool { false }
1008
1009 fn data(&self) -> Option<Value> {
1010 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1011 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1012 Some(Value::Array(vec![x.into(), y.into()]))
1013 }
1014
1015 fn py_cmd(&self) -> String {
1016 format!("ax.stem(data[0], data[1]{}{})",
1017 if self.opts.is_empty() { "" } else { ", " },
1018 self.opts.as_py(),
1019 )
1020 }
1021}
1022
1023impl MatplotlibOpts for Stem {
1024 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1025 self.opts.push((key, val).into());
1026 self
1027 }
1028}
1029
1030#[derive(Clone, Debug, PartialEq)]
1040pub struct Stairs {
1041 pub x: Vec<f64>,
1043 pub y: Vec<f64>,
1045 pub opts: Vec<Opt>,
1047}
1048
1049impl Stairs {
1050 pub fn new<X, XE, Y, YE>(x: X, y: Y) -> Self
1052 where
1053 X: IntoIterator<Item = XE>,
1054 XE: Real,
1055 Y: IntoIterator<Item = YE>,
1056 YE: Real,
1057 {
1058 Self {
1059 x: x.into_iter().map(Real::into_f64).collect(),
1060 y: y.into_iter().map(Real::into_f64).collect(),
1061 opts: Vec::new(),
1062 }
1063 }
1064
1065 pub fn new_pairs<I, XE, YE>(data: I) -> Self
1067 where
1068 I: IntoIterator<Item = (XE, YE)>,
1069 XE: Real,
1070 YE: Real,
1071 {
1072 let (x, y): (Vec<f64>, Vec<f64>) =
1073 data.into_iter()
1074 .map(|(x, y)| (x.into_f64(), y.into_f64()))
1075 .unzip();
1076 Self { x, y, opts: Vec::new() }
1077 }
1078}
1079
1080pub fn stairs<X, XE, Y, YE>(x: X, y: Y) -> Stairs
1082where
1083 X: IntoIterator<Item = XE>,
1084 XE: Real,
1085 Y: IntoIterator<Item = YE>,
1086 YE: Real,
1087{
1088 Stairs::new(x, y)
1089}
1090
1091pub fn stairs_pairs<I, XE, YE>(data: I) -> Stairs
1093where
1094 I: IntoIterator<Item = (XE, YE)>,
1095 XE: Real,
1096 YE: Real,
1097{
1098 Stairs::new_pairs(data)
1099}
1100
1101impl Matplotlib for Stairs {
1102 fn is_prelude(&self) -> bool { false }
1103
1104 fn data(&self) -> Option<Value> {
1105 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1106 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1107 Some(Value::Array(vec![x.into(), y.into()]))
1108 }
1109
1110 fn py_cmd(&self) -> String {
1111 format!("ax.stairs(data[1], data[0]{}{})",
1112 if self.opts.is_empty() { "" } else { ", " },
1113 self.opts.as_py(),
1114 )
1115 }
1116}
1117
1118impl MatplotlibOpts for Stairs {
1119 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1120 self.opts.push((key, val).into());
1121 self
1122 }
1123}
1124
1125#[derive(Clone, Debug, PartialEq)]
1135pub struct Step {
1136 pub x: Vec<f64>,
1138 pub y: Vec<f64>,
1140 pub opts: Vec<Opt>,
1142}
1143
1144impl Step {
1145 pub fn new<X, XE, Y, YE>(x: X, y: Y) -> Self
1147 where
1148 X: IntoIterator<Item = XE>,
1149 XE: Real,
1150 Y: IntoIterator<Item = YE>,
1151 YE: Real,
1152 {
1153 Self {
1154 x: x.into_iter().map(Real::into_f64).collect(),
1155 y: y.into_iter().map(Real::into_f64).collect(),
1156 opts: Vec::new(),
1157 }
1158 }
1159
1160 pub fn new_pairs<I, XE, YE>(data: I) -> Self
1162 where
1163 I: IntoIterator<Item = (XE, YE)>,
1164 XE: Real,
1165 YE: Real,
1166 {
1167 let (x, y): (Vec<f64>, Vec<f64>) =
1168 data.into_iter()
1169 .map(|(x, y)| (x.into_f64(), y.into_f64()))
1170 .unzip();
1171 Self { x, y, opts: Vec::new() }
1172 }
1173}
1174
1175pub fn step<X, XE, Y, YE>(x: X, y: Y) -> Step
1177where
1178 X: IntoIterator<Item = XE>,
1179 XE: Real,
1180 Y: IntoIterator<Item = YE>,
1181 YE: Real,
1182{
1183 Step::new(x, y)
1184}
1185
1186pub fn step_pairs<I, XE, YE>(data: I) -> Step
1188where
1189 I: IntoIterator<Item = (XE, YE)>,
1190 XE: Real,
1191 YE: Real,
1192{
1193 Step::new_pairs(data)
1194}
1195
1196impl Matplotlib for Step {
1197 fn is_prelude(&self) -> bool { false }
1198
1199 fn data(&self) -> Option<Value> {
1200 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1201 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1202 Some(Value::Array(vec![x.into(), y.into()]))
1203 }
1204
1205 fn py_cmd(&self) -> String {
1206 format!("ax.step(data[0], data[1]{}{})",
1207 if self.opts.is_empty() { "" } else { ", " },
1208 self.opts.as_py(),
1209 )
1210 }
1211}
1212
1213impl MatplotlibOpts for Step {
1214 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1215 self.opts.push((key, val).into());
1216 self
1217 }
1218}
1219
1220#[derive(Clone, Debug, PartialEq)]
1230pub struct Quiver {
1231 pub x: Vec<f64>,
1233 pub y: Vec<f64>,
1235 pub vx: Vec<f64>,
1237 pub vy: Vec<f64>,
1239 pub opts: Vec<Opt>,
1241}
1242
1243impl Quiver {
1244 pub fn new<X, XE, Y, YE, VX, VXE, VY, VYE>(
1246 x: X,
1247 y: Y,
1248 vx: VX,
1249 vy: VY,
1250 ) -> Self
1251 where
1252 X: IntoIterator<Item = XE>,
1253 XE: Real,
1254 Y: IntoIterator<Item = YE>,
1255 YE: Real,
1256 VX: IntoIterator<Item = VXE>,
1257 VXE: Real,
1258 VY: IntoIterator<Item = VYE>,
1259 VYE: Real,
1260 {
1261 Self {
1262 x: x.into_iter().map(Real::into_f64).collect(),
1263 y: y.into_iter().map(Real::into_f64).collect(),
1264 vx: vx.into_iter().map(Real::into_f64).collect(),
1265 vy: vy.into_iter().map(Real::into_f64).collect(),
1266 opts: Vec::new(),
1267 }
1268 }
1269
1270 pub fn new_pairs<I, XE, YE, VI, VXE, VYE>(xy: I, vxy: VI) -> Self
1273 where
1274 I: IntoIterator<Item = (XE, YE)>,
1275 XE: Real,
1276 YE: Real,
1277 VI: IntoIterator<Item = (VXE, VYE)>,
1278 VXE: Real,
1279 VYE: Real,
1280 {
1281 let (x, y): (Vec<f64>, Vec<f64>) =
1282 xy.into_iter()
1283 .map(|(x, y)| (x.into_f64(), y.into_f64()))
1284 .unzip();
1285 let (vx, vy): (Vec<f64>, Vec<f64>) =
1286 vxy.into_iter()
1287 .map(|(x, y)| (x.into_f64(), y.into_f64()))
1288 .unzip();
1289 Self { x, y, vx, vy, opts: Vec::new() }
1290 }
1291
1292 pub fn new_data<I, XE, YE, VXE, VYE>(data: I) -> Self
1296 where
1297 I: IntoIterator<Item = (XE, YE, VXE, VYE)>,
1298 XE: Real,
1299 YE: Real,
1300 VXE: Real,
1301 VYE: Real,
1302 {
1303 let (((x, y), vx), vy) =
1304 data.into_iter()
1305 .map(|(a, b, c, d)| {
1306 (a.into_f64(), b.into_f64(), c.into_f64(), d.into_f64())
1307 })
1308 .map(assoc)
1309 .unzip();
1310 Self { x, y, vx, vy, opts: Vec::new() }
1311 }
1312}
1313
1314pub fn quiver<X, XE, Y, YE, VX, VXE, VY, VYE>(
1316 x: X,
1317 y: Y,
1318 vx: VX,
1319 vy: VY,
1320) -> Quiver
1321where
1322 X: IntoIterator<Item = XE>,
1323 XE: Real,
1324 Y: IntoIterator<Item = YE>,
1325 YE: Real,
1326 VX: IntoIterator<Item = VXE>,
1327 VXE: Real,
1328 VY: IntoIterator<Item = VYE>,
1329 VYE: Real,
1330{
1331 Quiver::new(x, y, vx, vy)
1332}
1333
1334pub fn quiver_pairs<I, XE, YE, VI, VXE, VYE>(xy: I, vxy: VI) -> Quiver
1337where
1338 I: IntoIterator<Item = (XE, YE)>,
1339 XE: Real,
1340 YE: Real,
1341 VI: IntoIterator<Item = (VXE, VYE)>,
1342 VXE: Real,
1343 VYE: Real,
1344{
1345 Quiver::new_pairs(xy, vxy)
1346}
1347
1348pub fn quiver_data<I, XE, YE, VXE, VYE>(data: I) -> Quiver
1352where
1353 I: IntoIterator<Item = (XE, YE, VXE, VYE)>,
1354 XE: Real,
1355 YE: Real,
1356 VXE: Real,
1357 VYE: Real,
1358{
1359 Quiver::new_data(data)
1360}
1361
1362impl Matplotlib for Quiver {
1363 fn is_prelude(&self) -> bool { false }
1364
1365 fn data(&self) -> Option<Value> {
1366 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1367 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1368 let vx: Vec<Value> = self.vx.iter().copied().map(Value::from).collect();
1369 let vy: Vec<Value> = self.vy.iter().copied().map(Value::from).collect();
1370 Some(Value::Array(vec![x.into(), y.into(), vx.into(), vy.into()]))
1371 }
1372
1373 fn py_cmd(&self) -> String {
1374 format!("ax.quiver(data[0], data[1], data[2], data[3]{}{})",
1375 if self.opts.is_empty() { "" } else { ", " },
1376 self.opts.as_py(),
1377 )
1378 }
1379}
1380
1381impl MatplotlibOpts for Quiver {
1382 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1383 self.opts.push((key, val).into());
1384 self
1385 }
1386}
1387
1388#[derive(Clone, Debug, PartialEq)]
1398pub struct Bar {
1399 pub x: Vec<f64>,
1401 pub y: Vec<f64>,
1403 pub opts: Vec<Opt>,
1405}
1406
1407impl Bar {
1408 pub fn new<X, XE, Y, YE>(x: X, y: Y) -> Self
1410 where
1411 X: IntoIterator<Item = XE>,
1412 XE: Real,
1413 Y: IntoIterator<Item = YE>,
1414 YE: Real,
1415 {
1416 Self {
1417 x: x.into_iter().map(Real::into_f64).collect(),
1418 y: y.into_iter().map(Real::into_f64).collect(),
1419 opts: Vec::new(),
1420 }
1421 }
1422
1423 pub fn new_pairs<I, XE, YE>(data: I) -> Self
1425 where
1426 I: IntoIterator<Item = (XE, YE)>,
1427 XE: Real,
1428 YE: Real,
1429 {
1430 let (x, y): (Vec<f64>, Vec<f64>) =
1431 data.into_iter()
1432 .map(|(x, y)| (x.into_f64(), y.into_f64()))
1433 .unzip();
1434 Self { x, y, opts: Vec::new() }
1435 }
1436}
1437
1438pub fn bar<X, XE, Y, YE>(x: X, y: Y) -> Bar
1440where
1441 X: IntoIterator<Item = XE>,
1442 XE: Real,
1443 Y: IntoIterator<Item = YE>,
1444 YE: Real,
1445{
1446 Bar::new(x, y)
1447}
1448
1449pub fn bar_pairs<I, XE, YE>(data: I) -> Bar
1451where
1452 I: IntoIterator<Item = (XE, YE)>,
1453 XE: Real,
1454 YE: Real,
1455{
1456 Bar::new_pairs(data)
1457}
1458
1459impl Matplotlib for Bar {
1460 fn is_prelude(&self) -> bool { false }
1461
1462 fn data(&self) -> Option<Value> {
1463 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1464 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1465 Some(Value::Array(vec![x.into(), y.into()]))
1466 }
1467
1468 fn py_cmd(&self) -> String {
1469 format!("ax.bar(data[0], data[1]{}{})",
1470 if self.opts.is_empty() { "" } else { ", " },
1471 self.opts.as_py(),
1472 )
1473 }
1474}
1475
1476impl MatplotlibOpts for Bar {
1477 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1478 self.opts.push((key, val).into());
1479 self
1480 }
1481}
1482
1483#[derive(Clone, Debug, PartialEq)]
1493pub struct BarH {
1494 pub y: Vec<f64>,
1496 pub w: Vec<f64>,
1498 pub opts: Vec<Opt>,
1500}
1501
1502impl BarH {
1503 pub fn new<Y, YE, W, WE>(y: Y, w: W) -> Self
1505 where
1506 Y: IntoIterator<Item = YE>,
1507 YE: Real,
1508 W: IntoIterator<Item = WE>,
1509 WE: Real,
1510 {
1511 Self {
1512 y: y.into_iter().map(Real::into_f64).collect(),
1513 w: w.into_iter().map(Real::into_f64).collect(),
1514 opts: Vec::new(),
1515 }
1516 }
1517
1518 pub fn new_pairs<I, YE, WE>(data: I) -> Self
1520 where
1521 I: IntoIterator<Item = (YE, WE)>,
1522 YE: Real,
1523 WE: Real,
1524 {
1525 let (y, w): (Vec<f64>, Vec<f64>) =
1526 data.into_iter()
1527 .map(|(y, w)| (y.into_f64(), w.into_f64()))
1528 .unzip();
1529 Self { y, w, opts: Vec::new() }
1530 }
1531}
1532
1533pub fn barh<Y, YE, W, WE>(y: Y, w: W) -> BarH
1535where
1536 Y: IntoIterator<Item = YE>,
1537 YE: Real,
1538 W: IntoIterator<Item = WE>,
1539 WE: Real,
1540{
1541 BarH::new(y, w)
1542}
1543
1544pub fn barh_pairs<I, YE, WE>(data: I) -> BarH
1546where
1547 I: IntoIterator<Item = (YE, WE)>,
1548 YE: Real,
1549 WE: Real,
1550{
1551 BarH::new_pairs(data)
1552}
1553
1554impl Matplotlib for BarH {
1555 fn is_prelude(&self) -> bool { false }
1556
1557 fn data(&self) -> Option<Value> {
1558 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1559 let w: Vec<Value> = self.w.iter().copied().map(Value::from).collect();
1560 Some(Value::Array(vec![y.into(), w.into()]))
1561 }
1562
1563 fn py_cmd(&self) -> String {
1564 format!("ax.barh(data[0], data[1]{}{})",
1565 if self.opts.is_empty() { "" } else { ", " },
1566 self.opts.as_py(),
1567 )
1568 }
1569}
1570
1571impl MatplotlibOpts for BarH {
1572 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1573 self.opts.push((key, val).into());
1574 self
1575 }
1576}
1577
1578#[derive(Clone, Debug, PartialEq)]
1588pub struct Errorbar {
1589 pub x: Vec<f64>,
1591 pub y: Vec<f64>,
1593 pub e: Vec<f64>,
1595 pub opts: Vec<Opt>,
1597}
1598
1599impl Errorbar {
1600 pub fn new<X, XE, Y, YE, E, EE>(x: X, y: Y, e: E) -> Self
1602 where
1603 X: IntoIterator<Item = XE>,
1604 XE: Real,
1605 Y: IntoIterator<Item = YE>,
1606 YE: Real,
1607 E: IntoIterator<Item = EE>,
1608 EE: Real,
1609 {
1610 Self {
1611 x: x.into_iter().map(Real::into_f64).collect(),
1612 y: y.into_iter().map(Real::into_f64).collect(),
1613 e: e.into_iter().map(Real::into_f64).collect(),
1614 opts: Vec::new(),
1615 }
1616 }
1617
1618 pub fn new_data<I, XE, YE, EE>(data: I) -> Self
1620 where
1621 I: IntoIterator<Item = (XE, YE, EE)>,
1622 XE: Real,
1623 YE: Real,
1624 EE: Real,
1625 {
1626 let ((x, y), e) =
1627 data.into_iter()
1628 .map(|(a, b, c)| (a.into_f64(), b.into_f64(), c.into_f64()))
1629 .map(assoc)
1630 .unzip();
1631 Self { x, y, e, opts: Vec::new() }
1632 }
1633}
1634
1635pub fn errorbar<X, XE, Y, YE, E, EE>(x: X, y: Y, e: E) -> Errorbar
1637where
1638 X: IntoIterator<Item = XE>,
1639 XE: Real,
1640 Y: IntoIterator<Item = YE>,
1641 YE: Real,
1642 E: IntoIterator<Item = EE>,
1643 EE: Real,
1644{
1645 Errorbar::new(x, y, e)
1646}
1647
1648pub fn errorbar_data<I, XE, YE, EE>(data: I) -> Errorbar
1650where
1651 I: IntoIterator<Item = (XE, YE, EE)>,
1652 XE: Real,
1653 YE: Real,
1654 EE: Real,
1655{
1656 Errorbar::new_data(data)
1657}
1658
1659impl Matplotlib for Errorbar {
1660 fn is_prelude(&self) -> bool { false }
1661
1662 fn data(&self) -> Option<Value> {
1663 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1664 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1665 let e: Vec<Value> = self.e.iter().copied().map(Value::from).collect();
1666 Some(Value::Array(vec![x.into(), y.into(), e.into()]))
1667 }
1668
1669 fn py_cmd(&self) -> String {
1670 format!("ax.errorbar(data[0], data[1], data[2]{}{})",
1671 if self.opts.is_empty() { "" } else { ", " },
1672 self.opts.as_py(),
1673 )
1674 }
1675}
1676
1677impl MatplotlibOpts for Errorbar {
1678 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1679 self.opts.push((key, val).into());
1680 self
1681 }
1682}
1683
1684impl From<FillBetween> for Errorbar {
1686 fn from(fill_between: FillBetween) -> Self {
1687 let FillBetween { x, mut y1, mut y2, opts } = fill_between;
1688 y1.iter_mut()
1689 .zip(y2.iter_mut())
1690 .for_each(|(y1k, y2k)| {
1691 let y1 = *y1k;
1692 let y2 = *y2k;
1693 *y1k = 0.5 * (y1 + y2);
1694 *y2k = 0.5 * (y1 - y2).abs();
1695 });
1696 Self { x, y: y1, e: y2, opts }
1697 }
1698}
1699
1700#[derive(Clone, Debug, PartialEq)]
1710pub struct Errorbar2 {
1711 pub x: Vec<f64>,
1713 pub y: Vec<f64>,
1715 pub e_neg: Vec<f64>,
1717 pub e_pos: Vec<f64>,
1719 pub opts: Vec<Opt>,
1721}
1722
1723impl Errorbar2 {
1724 pub fn new<X, XE, Y, YE, E1, E1E, E2, E2E>(
1726 x: X,
1727 y: Y,
1728 e_neg: E1,
1729 e_pos: E2,
1730 ) -> Self
1731 where
1732 X: IntoIterator<Item = XE>,
1733 XE: Real,
1734 Y: IntoIterator<Item = YE>,
1735 YE: Real,
1736 E1: IntoIterator<Item = E1E>,
1737 E1E: Real,
1738 E2: IntoIterator<Item = E2E>,
1739 E2E: Real,
1740 {
1741 Self {
1742 x: x.into_iter().map(Real::into_f64).collect(),
1743 y: y.into_iter().map(Real::into_f64).collect(),
1744 e_neg: e_neg.into_iter().map(Real::into_f64).collect(),
1745 e_pos: e_pos.into_iter().map(Real::into_f64).collect(),
1746 opts: Vec::new(),
1747 }
1748 }
1749
1750 pub fn new_data<I, XE, YE, E1E, E2E>(data: I) -> Self
1752 where
1753 I: IntoIterator<Item = (XE, YE, E1E, E2E)>,
1754 XE: Real,
1755 YE: Real,
1756 E1E: Real,
1757 E2E: Real,
1758 {
1759 let (((x, y), e_neg), e_pos) =
1760 data.into_iter()
1761 .map(|(a, b, c, d)| {
1762 (a.into_f64(), b.into_f64(), c.into_f64(), d.into_f64())
1763 })
1764 .map(assoc)
1765 .unzip();
1766 Self { x, y, e_neg, e_pos, opts: Vec::new() }
1767 }
1768}
1769
1770pub fn errorbar2<X, XE, Y, YE, E1, E1E, E2, E2E>(
1772 x: X,
1773 y: Y,
1774 e_neg: E1,
1775 e_pos: E2,
1776) -> Errorbar2
1777where
1778 X: IntoIterator<Item = XE>,
1779 XE: Real,
1780 Y: IntoIterator<Item = YE>,
1781 YE: Real,
1782 E1: IntoIterator<Item = E1E>,
1783 E1E: Real,
1784 E2: IntoIterator<Item = E2E>,
1785 E2E: Real,
1786{
1787 Errorbar2::new(x, y, e_neg, e_pos)
1788}
1789
1790pub fn errorbar2_data<I, XE, YE, E1E, E2E>(data: I) -> Errorbar2
1792where
1793 I: IntoIterator<Item = (XE, YE, E1E, E2E)>,
1794 XE: Real,
1795 YE: Real,
1796 E1E: Real,
1797 E2E: Real,
1798{
1799 Errorbar2::new_data(data)
1800}
1801
1802impl Matplotlib for Errorbar2 {
1803 fn is_prelude(&self) -> bool { false }
1804
1805 fn data(&self) -> Option<Value> {
1806 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1807 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1808 let e_neg: Vec<Value> =
1809 self.e_neg.iter().copied().map(Value::from).collect();
1810 let e_pos: Vec<Value> =
1811 self.e_pos.iter().copied().map(Value::from).collect();
1812 Some(Value::Array(
1813 vec![x.into(), y.into(), e_neg.into(), e_pos.into()]))
1814 }
1815
1816 fn py_cmd(&self) -> String {
1817 format!("ax.errorbar(data[0], data[1], [data[2], data[3]]{}{})",
1818 if self.opts.is_empty() { "" } else { ", " },
1819 self.opts.as_py(),
1820 )
1821 }
1822}
1823
1824impl MatplotlibOpts for Errorbar2 {
1825 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1826 self.opts.push((key, val).into());
1827 self
1828 }
1829}
1830
1831struct Chunks<I, T>
1832where I: Iterator<Item = T>
1833{
1834 chunksize: usize,
1835 buflen: usize,
1836 buf: Vec<T>,
1837 iter: I,
1838}
1839
1840impl<I, T> Chunks<I, T>
1841where I: Iterator<Item = T>
1842{
1843 fn new(iter: I, chunksize: usize) -> Self {
1844 if chunksize == 0 { panic!("chunk size cannot be zero"); }
1845 Self {
1846 chunksize,
1847 buflen: 0,
1848 buf: Vec::with_capacity(chunksize),
1849 iter,
1850 }
1851 }
1852}
1853
1854impl<I, T> Iterator for Chunks<I, T>
1855where I: Iterator<Item = T>
1856{
1857 type Item = Vec<T>;
1858
1859 fn next(&mut self) -> Option<Self::Item> {
1860 loop {
1861 if let Some(item) = self.iter.next() {
1862 self.buf.push(item);
1863 self.buflen += 1;
1864 if self.buflen == self.chunksize {
1865 let mut bufswap = Vec::with_capacity(self.chunksize);
1866 std::mem::swap(&mut bufswap, &mut self.buf);
1867 self.buflen = 0;
1868 return Some(bufswap);
1869 } else {
1870 continue;
1871 }
1872 } else if self.buflen > 0 {
1873 let mut bufswap = Vec::with_capacity(0);
1874 std::mem::swap(&mut bufswap, &mut self.buf);
1875 self.buflen = 0;
1876 return Some(bufswap);
1877 } else {
1878 return None;
1879 }
1880 }
1881 }
1882}
1883
1884
1885#[derive(Clone, Debug, PartialEq)]
1895pub struct Boxplot {
1896 pub data: Vec<Vec<f64>>,
1898 pub opts: Vec<Opt>,
1900}
1901
1902impl Boxplot {
1903 pub fn new<I, J, E>(data: I) -> Self
1905 where
1906 I: IntoIterator<Item = J>,
1907 J: IntoIterator<Item = E>,
1908 E: Real,
1909 {
1910 let data: Vec<Vec<f64>> =
1911 data.into_iter()
1912 .map(|row| row.into_iter().map(Real::into_f64).collect())
1913 .collect();
1914 Self { data, opts: Vec::new() }
1915 }
1916
1917 pub fn new_flat<I, E>(data: I, size: usize) -> Self
1925 where
1926 I: IntoIterator<Item = E>,
1927 E: Real,
1928 {
1929 if size == 0 { panic!("data set size cannot be zero"); }
1930 let data: Vec<Vec<f64>> =
1931 Chunks::new(data.into_iter().map(Real::into_f64), size)
1932 .collect();
1933 Self { data, opts: Vec::new() }
1934 }
1935}
1936
1937pub fn boxplot<I, J, E>(data: I) -> Boxplot
1939where
1940 I: IntoIterator<Item = J>,
1941 J: IntoIterator<Item = E>,
1942 E: Real,
1943{
1944 Boxplot::new(data)
1945}
1946
1947pub fn boxplot_flat<I, E>(data: I, size: usize) -> Boxplot
1955where
1956 I: IntoIterator<Item = E>,
1957 E: Real,
1958{
1959 Boxplot::new_flat(data, size)
1960}
1961
1962impl Matplotlib for Boxplot {
1963 fn is_prelude(&self) -> bool { false }
1964
1965 fn data(&self) -> Option<Value> {
1966 let data: Vec<Value> =
1967 self.data.iter()
1968 .map(|row| {
1969 let row: Vec<Value> =
1970 row.iter().copied().map(Value::from).collect();
1971 Value::Array(row)
1972 })
1973 .collect();
1974 Some(Value::Array(data))
1975 }
1976
1977 fn py_cmd(&self) -> String {
1978 format!("ax.boxplot(data{}{})",
1979 if self.opts.is_empty() { "" } else { ", " },
1980 self.opts.as_py(),
1981 )
1982 }
1983}
1984
1985impl MatplotlibOpts for Boxplot {
1986 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1987 self.opts.push((key, val).into());
1988 self
1989 }
1990}
1991
1992#[derive(Clone, Debug, PartialEq)]
2002pub struct Violinplot {
2003 pub data: Vec<Vec<f64>>,
2005 pub opts: Vec<Opt>,
2007}
2008
2009impl Violinplot {
2010 pub fn new<I, J, E>(data: I) -> Self
2012 where
2013 I: IntoIterator<Item = J>,
2014 J: IntoIterator<Item = E>,
2015 E: Real,
2016 {
2017 let data: Vec<Vec<f64>> =
2018 data.into_iter()
2019 .map(|row| row.into_iter().map(Real::into_f64).collect())
2020 .collect();
2021 Self { data, opts: Vec::new() }
2022 }
2023
2024 pub fn new_flat<I, E>(data: I, size: usize) -> Self
2032 where
2033 I: IntoIterator<Item = E>,
2034 E: Real,
2035 {
2036 if size == 0 { panic!("data set size cannot be zero"); }
2037 let data: Vec<Vec<f64>> =
2038 Chunks::new(data.into_iter().map(Real::into_f64), size)
2039 .collect();
2040 Self { data, opts: Vec::new() }
2041 }
2042}
2043
2044pub fn violinplot<I, J, E>(data: I) -> Violinplot
2046where
2047 I: IntoIterator<Item = J>,
2048 J: IntoIterator<Item = E>,
2049 E: Real,
2050{
2051 Violinplot::new(data)
2052}
2053
2054pub fn violinplot_flat<I, E>(data: I, size: usize) -> Violinplot
2062where
2063 I: IntoIterator<Item = E>,
2064 E: Real,
2065{
2066 Violinplot::new_flat(data, size)
2067}
2068
2069impl Matplotlib for Violinplot {
2070 fn is_prelude(&self) -> bool { false }
2071
2072 fn data(&self) -> Option<Value> {
2073 let data: Vec<Value> =
2074 self.data.iter()
2075 .map(|row| {
2076 let row: Vec<Value> =
2077 row.iter().copied().map(Value::from).collect();
2078 Value::Array(row)
2079 })
2080 .collect();
2081 Some(Value::Array(data))
2082 }
2083
2084 fn py_cmd(&self) -> String {
2085 format!("ax.violinplot(data{}{})",
2086 if self.opts.is_empty() { "" } else { ", " },
2087 self.opts.as_py(),
2088 )
2089 }
2090}
2091
2092impl MatplotlibOpts for Violinplot {
2093 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2094 self.opts.push((key, val).into());
2095 self
2096 }
2097}
2098
2099#[derive(Clone, Debug, PartialEq)]
2114pub struct Contour {
2115 pub x: Vec<f64>,
2117 pub y: Vec<f64>,
2119 pub z: Vec<Vec<f64>>,
2123 pub opts: Vec<Opt>,
2125}
2126
2127impl Contour {
2128 pub fn new<X, XE, Y, YE, ZI, ZJ, ZE>(x: X, y: Y, z: ZI) -> Self
2130 where
2131 X: IntoIterator<Item = XE>,
2132 XE: Real,
2133 Y: IntoIterator<Item = YE>,
2134 YE: Real,
2135 ZI: IntoIterator<Item = ZJ>,
2136 ZJ: IntoIterator<Item = ZE>,
2137 ZE: Real,
2138 {
2139 let x: Vec<f64> = x.into_iter().map(Real::into_f64).collect();
2140 let y: Vec<f64> = y.into_iter().map(Real::into_f64).collect();
2141 let z: Vec<Vec<f64>> =
2142 z.into_iter()
2143 .map(|row| row.into_iter().map(Real::into_f64).collect())
2144 .collect();
2145 Self { x, y, z, opts: Vec::new() }
2146 }
2147
2148 pub fn new_flat<X, XE, Y, YE, Z, ZE>(x: X, y: Y, z: Z) -> Self
2153 where
2154 X: IntoIterator<Item = XE>,
2155 XE: Real,
2156 Y: IntoIterator<Item = YE>,
2157 YE: Real,
2158 Z: IntoIterator<Item = ZE>,
2159 ZE: Real,
2160 {
2161 let x: Vec<f64> = x.into_iter().map(Real::into_f64).collect();
2162 if x.is_empty() { panic!("x-coordinate array cannot be empty"); }
2163 let y: Vec<f64> = y.into_iter().map(Real::into_f64).collect();
2164 let z: Vec<Vec<f64>> =
2165 Chunks::new(z.into_iter().map(Real::into_f64), x.len())
2166 .collect();
2167 Self { x, y, z, opts: Vec::new() }
2168 }
2169}
2170
2171pub fn contour<X, XE, Y, YE, ZI, ZJ, ZE>(x: X, y: Y, z: ZI) -> Contour
2173where
2174 X: IntoIterator<Item = XE>,
2175 XE: Real,
2176 Y: IntoIterator<Item = YE>,
2177 YE: Real,
2178 ZI: IntoIterator<Item = ZJ>,
2179 ZJ: IntoIterator<Item = ZE>,
2180 ZE: Real,
2181{
2182 Contour::new(x, y, z)
2183}
2184
2185pub fn contour_flat<X, XE, Y, YE, Z, ZE>(x: X, y: Y, z: Z) -> Contour
2190where
2191 X: IntoIterator<Item = XE>,
2192 XE: Real,
2193 Y: IntoIterator<Item = YE>,
2194 YE: Real,
2195 Z: IntoIterator<Item = ZE>,
2196 ZE: Real,
2197{
2198 Contour::new_flat(x, y, z)
2199}
2200
2201impl Matplotlib for Contour {
2202 fn is_prelude(&self) -> bool { false }
2203
2204 fn data(&self) -> Option<Value> {
2205 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
2206 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
2207 let z: Vec<Value> =
2208 self.z.iter()
2209 .map(|row| {
2210 let row: Vec<Value> =
2211 row.iter().copied().map(Value::from).collect();
2212 Value::Array(row)
2213 })
2214 .collect();
2215 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
2216 }
2217
2218 fn py_cmd(&self) -> String {
2219 format!("im = ax.contour(data[0], data[1], data[2]{}{})",
2220 if self.opts.is_empty() { "" } else { ", " },
2221 self.opts.as_py(),
2222 )
2223 }
2224}
2225
2226impl MatplotlibOpts for Contour {
2227 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2228 self.opts.push((key, val).into());
2229 self
2230 }
2231}
2232
2233#[derive(Clone, Debug, PartialEq, Default)]
2243pub struct ContourLabels {
2244 pub levels: Option<Vec<f64>>,
2248 pub fmt: Option<(String, Raw)>,
2253 pub opts: Vec<Opt>,
2255}
2256
2257impl ContourLabels {
2258 pub fn new() -> Self {
2260 Self { levels: None, fmt: None, opts: Vec::new() }
2261 }
2262
2263 pub fn new_levels<I, E>(levels: I) -> Self
2266 where
2267 I: IntoIterator<Item = E>,
2268 E: Real,
2269 {
2270 Self {
2271 levels: Some(levels.into_iter().map(Real::into_f64).collect()),
2272 fmt: None,
2273 opts: Vec::new(),
2274 }
2275 }
2276
2277 pub fn on_levels<I, E>(mut self, levels: I) -> Self
2279 where
2280 I: IntoIterator<Item = E>,
2281 E: Real,
2282 {
2283 self.levels = Some(levels.into_iter().map(Real::into_f64).collect());
2284 self
2285 }
2286
2287 pub fn with_fmt(mut self, arg: &str, body: &str) -> Self {
2292 self.fmt = Some((arg.to_string(), Raw(body.to_string())));
2293 self
2294 }
2295}
2296
2297pub fn contour_labels() -> ContourLabels {
2299 ContourLabels::new()
2300}
2301
2302impl Matplotlib for ContourLabels {
2303 fn is_prelude(&self) -> bool { false }
2304
2305 fn data(&self) -> Option<Value> { None }
2306
2307 fn py_cmd(&self) -> String {
2308 let levels_str =
2309 if let Some(levels) = self.levels.as_ref() {
2310 let mut acc = ", [".to_string();
2311 let n = levels.len();
2312 for (k, level) in levels.iter().enumerate() {
2313 acc += &level.as_py();
2314 if k < n - 1 { acc += ", "; }
2315 }
2316 acc += "]";
2317 acc
2318 } else {
2319 ", im.levels".to_string()
2320 };
2321 let fmt_str =
2322 if let Some((arg, Raw(body))) = self.fmt.as_ref() {
2323 format!(", fmt=lambda {}: {}", arg, body)
2324 } else {
2325 "".to_string()
2326 };
2327 format!("ax.clabel(im{}{}{}{})",
2328 levels_str,
2329 fmt_str,
2330 if self.opts.is_empty() { "" } else { ", " },
2331 self.opts.as_py(),
2332 )
2333 }
2334}
2335
2336impl MatplotlibOpts for ContourLabels {
2337 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2338 self.opts.push((key, val).into());
2339 self
2340 }
2341}
2342
2343#[derive(Clone, Debug, PartialEq)]
2358pub struct Contourf {
2359 pub x: Vec<f64>,
2361 pub y: Vec<f64>,
2363 pub z: Vec<Vec<f64>>,
2367 pub opts: Vec<Opt>,
2369}
2370
2371impl Contourf {
2372 pub fn new<X, XE, Y, YE, ZI, ZJ, ZE>(x: X, y: Y, z: ZI) -> Self
2374 where
2375 X: IntoIterator<Item = XE>,
2376 XE: Real,
2377 Y: IntoIterator<Item = YE>,
2378 YE: Real,
2379 ZI: IntoIterator<Item = ZJ>,
2380 ZJ: IntoIterator<Item = ZE>,
2381 ZE: Real,
2382 {
2383 let x: Vec<f64> = x.into_iter().map(Real::into_f64).collect();
2384 let y: Vec<f64> = y.into_iter().map(Real::into_f64).collect();
2385 let z: Vec<Vec<f64>> =
2386 z.into_iter()
2387 .map(|row| row.into_iter().map(Real::into_f64).collect())
2388 .collect();
2389 Self { x, y, z, opts: Vec::new() }
2390 }
2391
2392 pub fn new_flat<X, XE, Y, YE, Z, ZE>(x: X, y: Y, z: Z) -> Self
2397 where
2398 X: IntoIterator<Item = XE>,
2399 XE: Real,
2400 Y: IntoIterator<Item = YE>,
2401 YE: Real,
2402 Z: IntoIterator<Item = ZE>,
2403 ZE: Real,
2404 {
2405 let x: Vec<f64> = x.into_iter().map(Real::into_f64).collect();
2406 if x.is_empty() { panic!("x-coordinate array cannot be empty"); }
2407 let y: Vec<f64> = y.into_iter().map(Real::into_f64).collect();
2408 let z: Vec<Vec<f64>> =
2409 Chunks::new(z.into_iter().map(Real::into_f64), x.len())
2410 .collect();
2411 Self { x, y, z, opts: Vec::new() }
2412 }
2413}
2414
2415pub fn contourf<X, XE, Y, YE, ZI, ZJ, ZE>(x: X, y: Y, z: ZI) -> Contourf
2417where
2418 X: IntoIterator<Item = XE>,
2419 XE: Real,
2420 Y: IntoIterator<Item = YE>,
2421 YE: Real,
2422 ZI: IntoIterator<Item = ZJ>,
2423 ZJ: IntoIterator<Item = ZE>,
2424 ZE: Real,
2425{
2426 Contourf::new(x, y, z)
2427}
2428
2429pub fn contourf_flat<X, XE, Y, YE, Z, ZE>(x: X, y: Y, z: Z) -> Contourf
2434where
2435 X: IntoIterator<Item = XE>,
2436 XE: Real,
2437 Y: IntoIterator<Item = YE>,
2438 YE: Real,
2439 Z: IntoIterator<Item = ZE>,
2440 ZE: Real,
2441{
2442 Contourf::new_flat(x, y, z)
2443}
2444
2445impl Matplotlib for Contourf {
2446 fn is_prelude(&self) -> bool { false }
2447
2448 fn data(&self) -> Option<Value> {
2449 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
2450 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
2451 let z: Vec<Value> =
2452 self.z.iter()
2453 .map(|row| {
2454 let row: Vec<Value> =
2455 row.iter().copied().map(Value::from).collect();
2456 Value::Array(row)
2457 })
2458 .collect();
2459 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
2460 }
2461
2462 fn py_cmd(&self) -> String {
2463 format!("im = ax.contourf(data[0], data[1], data[2]{}{})",
2464 if self.opts.is_empty() { "" } else { ", " },
2465 self.opts.as_py(),
2466 )
2467 }
2468}
2469
2470impl MatplotlibOpts for Contourf {
2471 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2472 self.opts.push((key, val).into());
2473 self
2474 }
2475}
2476
2477#[derive(Copy, Clone, Debug, PartialEq)]
2482pub enum ColorCell {
2483 Scalar(f64),
2484 Rgb(u8, u8, u8),
2485 RgbFloat(f64, f64, f64),
2486 Rgba(u8, u8, u8, u8),
2487 RgbaFloat(f64, f64, f64, f64),
2488}
2489
2490impl From<f64> for ColorCell {
2491 fn from(x: f64) -> Self { Self::Scalar(x) }
2492}
2493
2494impl From<&f64> for ColorCell {
2495 fn from(x: &f64) -> Self { Self::Scalar(*x) }
2496}
2497
2498impl From<(u8, u8, u8)> for ColorCell {
2499 fn from((r, g, b): (u8, u8, u8)) -> Self { Self::Rgb(r, g, b) }
2500}
2501
2502impl From<&(u8, u8, u8)> for ColorCell {
2503 fn from((r, g, b): &(u8, u8, u8)) -> Self { Self::Rgb(*r, *g, *b) }
2504}
2505
2506impl From<(&u8, &u8, &u8)> for ColorCell {
2507 fn from((r, g, b): (&u8, &u8, &u8)) -> Self { Self::Rgb(*r, *g, *b) }
2508}
2509
2510impl From<(f64, f64, f64)> for ColorCell {
2511 fn from((r, g, b): (f64, f64, f64)) -> Self { Self::RgbFloat(r, g, b) }
2512}
2513
2514impl From<&(f64, f64, f64)> for ColorCell {
2515 fn from((r, g, b): &(f64, f64, f64)) -> Self { Self::RgbFloat(*r, *g, *b) }
2516}
2517
2518impl From<(&f64, &f64, &f64)> for ColorCell {
2519 fn from((r, g, b): (&f64, &f64, &f64)) -> Self {
2520 Self::RgbFloat(*r, *g, *b)
2521 }
2522}
2523
2524impl From<(u8, u8, u8, u8)> for ColorCell {
2525 fn from((r, g, b, a): (u8, u8, u8, u8)) -> Self { Self::Rgba(r, g, b, a) }
2526}
2527
2528impl From<&(u8, u8, u8, u8)> for ColorCell {
2529 fn from((r, g, b, a): &(u8, u8, u8, u8)) -> Self {
2530 Self::Rgba(*r, *g, *b, *a)
2531 }
2532}
2533
2534impl From<(&u8, &u8, &u8, &u8)> for ColorCell {
2535 fn from((r, g, b, a): (&u8, &u8, &u8, &u8)) -> Self {
2536 Self::Rgba(*r, *g, *b, *a)
2537 }
2538}
2539
2540impl From<(f64, f64, f64, f64)> for ColorCell {
2541 fn from((r, g, b, a): (f64, f64, f64, f64)) -> Self {
2542 Self::RgbaFloat(r, g, b, a)
2543 }
2544}
2545
2546impl From<&(f64, f64, f64, f64)> for ColorCell {
2547 fn from((r, g, b, a): &(f64, f64, f64, f64)) -> Self {
2548 Self::RgbaFloat(*r, *g, *b, *a)
2549 }
2550}
2551
2552impl From<(&f64, &f64, &f64, &f64)> for ColorCell {
2553 fn from((r, g, b, a): (&f64, &f64, &f64, &f64)) -> Self {
2554 Self::RgbaFloat(*r, *g, *b, *a)
2555 }
2556}
2557
2558impl From<ColorCell> for Value {
2559 fn from(cell: ColorCell) -> Self {
2560 match cell {
2561 ColorCell::Scalar(x) => Self::from(x),
2562 ColorCell::Rgb(r, g, b) => {
2563 let r = Number::from(r);
2564 let g = Number::from(g);
2565 let b = Number::from(b);
2566 Self::Array(vec![r.into(), g.into(), b.into()])
2567 },
2568 ColorCell::RgbFloat(r, g, b) => {
2569 let r = Number::from_f64(r)
2570 .expect("encountered infinity or NaN");
2571 let g = Number::from_f64(g)
2572 .expect("encountered infinity or NaN");
2573 let b = Number::from_f64(b)
2574 .expect("encountered infinity or NaN");
2575 Self::Array(vec![r.into(), g.into(), b.into()])
2576 },
2577 ColorCell::Rgba(r, g, b, a) => {
2578 let r = Number::from(r);
2579 let g = Number::from(g);
2580 let b = Number::from(b);
2581 let a = Number::from(a);
2582 Self::Array(vec![r.into(), g.into(), b.into(), a.into()])
2583 },
2584 ColorCell::RgbaFloat(r, g, b, a) => {
2585 let r = Number::from_f64(r)
2586 .expect("encountered infinity or NaN");
2587 let g = Number::from_f64(g)
2588 .expect("encountered infinity or NaN");
2589 let b = Number::from_f64(b)
2590 .expect("encountered infinity or NaN");
2591 let a = Number::from_f64(a)
2592 .expect("encountered infinity or NaN");
2593 Self::Array(vec![r.into(), g.into(), b.into(), a.into()])
2594 },
2595 }
2596 }
2597}
2598
2599impl From<ColorCell> for PyValue {
2600 fn from(cell: ColorCell) -> Self {
2601 match cell {
2602 ColorCell::Scalar(x) => Self::Float(x),
2603 ColorCell::Rgb(r, g, b) =>
2604 Self::list([r as i32, g as i32, b as i32]),
2605 ColorCell::RgbFloat(r, g, b) => Self::list([r, g, b]),
2606 ColorCell::Rgba(r, g, b, a) =>
2607 Self::list([r as i32, g as i32, b as i32, a as i32]),
2608 ColorCell::RgbaFloat(r, g, b, a) => Self::list([r, g, b, a]),
2609 }
2610 }
2611}
2612
2613#[derive(Clone, Debug, PartialEq)]
2626pub struct Imshow {
2627 pub data: Vec<Vec<ColorCell>>,
2629 pub opts: Vec<Opt>,
2631}
2632
2633impl Imshow {
2634 pub fn new<I, J, C>(data: I) -> Self
2636 where
2637 I: IntoIterator<Item = J>,
2638 J: IntoIterator<Item = C>,
2639 C: Into<ColorCell>,
2640 {
2641 let data: Vec<Vec<ColorCell>> =
2642 data.into_iter()
2643 .map(|row| row.into_iter().map(|c| c.into()).collect())
2644 .collect();
2645 Self { data, opts: Vec::new() }
2646 }
2647
2648 pub fn new_flat<I, C>(data: I, rowlen: usize) -> Self
2653 where
2654 I: IntoIterator<Item = C>,
2655 C: Into<ColorCell>,
2656 {
2657 if rowlen == 0 { panic!("row length cannot be zero"); }
2658 let data: Vec<Vec<ColorCell>> =
2659 Chunks::new(data.into_iter().map(|c| c.into()), rowlen)
2660 .collect();
2661 Self { data, opts: Vec::new() }
2662 }
2663
2664 pub fn new_flat_c<I, C>(data: I, collen: usize) -> Self
2669 where
2670 I: IntoIterator<Item = C>,
2671 C: Into<ColorCell>,
2672 {
2673 if collen == 0 { panic!("column length cannot be zero"); }
2674 let mut cells: Vec<Vec<ColorCell>> =
2675 (0 .. collen).map(|_| Vec::new()).collect();
2676 Chunks::new(data.into_iter().map(|c| c.into()), collen)
2677 .for_each(|chunk| {
2678 cells.iter_mut().zip(chunk)
2679 .for_each(|(cell, c)| { cell.push(c); });
2680 });
2681 Self { data: cells, opts: Vec::new() }
2682 }
2683}
2684
2685pub fn imshow<I, J, C>(data: I) -> Imshow
2687where
2688 I: IntoIterator<Item = J>,
2689 J: IntoIterator<Item = C>,
2690 C: Into<ColorCell>,
2691{
2692 Imshow::new(data)
2693}
2694
2695pub fn imshow_flat<I, C>(data: I, rowlen: usize) -> Imshow
2700where
2701 I: IntoIterator<Item = C>,
2702 C: Into<ColorCell>,
2703{
2704 Imshow::new_flat(data, rowlen)
2705}
2706
2707pub fn imshow_flat_c<I, C>(data: I, collen: usize) -> Imshow
2712where
2713 I: IntoIterator<Item = C>,
2714 C: Into<ColorCell>,
2715{
2716 Imshow::new_flat_c(data, collen)
2717}
2718
2719impl Matplotlib for Imshow {
2720 fn is_prelude(&self) -> bool { false }
2721
2722 fn data(&self) -> Option<Value> {
2723 let data: Vec<Value> =
2724 self.data.iter()
2725 .map(|row| {
2726 let row: Vec<Value> =
2727 row.iter().copied().map(Value::from).collect();
2728 Value::Array(row)
2729 })
2730 .collect();
2731 Some(Value::Array(data))
2732 }
2733
2734 fn py_cmd(&self) -> String {
2735 format!("im = ax.imshow(data{}{})",
2736 if self.opts.is_empty() { "" } else { ", " },
2737 self.opts.as_py(),
2738 )
2739 }
2740}
2741
2742impl MatplotlibOpts for Imshow {
2743 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2744 self.opts.push((key, val).into());
2745 self
2746 }
2747}
2748
2749#[derive(Clone, Debug, PartialEq)]
2778pub struct Colorplot {
2779 pub x: Vec<f64>,
2781 pub y: Vec<f64>,
2783 pub z: Vec<Vec<ColorCell>>,
2785 pub opts: Vec<Opt>,
2787}
2788
2789impl Colorplot {
2790 pub fn new<X, XE, Y, YE, I, J, C>(x: X, y: Y, z: I) -> Self
2792 where
2793 X: IntoIterator<Item = XE>,
2794 XE: Real,
2795 Y: IntoIterator<Item = YE>,
2796 YE: Real,
2797 I: IntoIterator<Item = J>,
2798 J: IntoIterator<Item = C>,
2799 C: Into<ColorCell>,
2800 {
2801 let x: Vec<f64> = x.into_iter().map(Real::into_f64).collect();
2802 let y: Vec<f64> = y.into_iter().map(Real::into_f64).collect();
2803 let z: Vec<Vec<ColorCell>> =
2804 z.into_iter()
2805 .map(|row| row.into_iter().map(|c| c.into()).collect())
2806 .collect();
2807 Self { x, y, z, opts: Vec::new() }
2808 }
2809
2810 pub fn new_flat<X, XE, Y, YE, Z, C>(x: X, y: Y, z: Z) -> Self
2813 where
2814 X: IntoIterator<Item = XE>,
2815 XE: Real,
2816 Y: IntoIterator<Item = YE>,
2817 YE: Real,
2818 Z: IntoIterator<Item = C>,
2819 C: Into<ColorCell>,
2820 {
2821 let x: Vec<f64> = x.into_iter().map(Real::into_f64).collect();
2822 let y: Vec<f64> = y.into_iter().map(Real::into_f64).collect();
2823 if x.is_empty() { panic!("x-coordinate array cannot be empty"); }
2824 let z: Vec<Vec<ColorCell>> =
2825 Chunks::new(z.into_iter().map(|c| c.into()), x.len())
2826 .collect();
2827 Self { x, y, z, opts: Vec::new() }
2828 }
2829
2830 pub fn new_flat_c<X, XE, Y, YE, Z, C>(x: X, y: Y, z: Z) -> Self
2833 where
2834 X: IntoIterator<Item = XE>,
2835 XE: Real,
2836 Y: IntoIterator<Item = YE>,
2837 YE: Real,
2838 Z: IntoIterator<Item = C>,
2839 C: Into<ColorCell>,
2840 {
2841 let x: Vec<f64> = x.into_iter().map(Real::into_f64).collect();
2842 let y: Vec<f64> = y.into_iter().map(Real::into_f64).collect();
2843 if y.is_empty() { panic!("y-coordinate array cannot be empty"); }
2844 let mut cells: Vec<Vec<ColorCell>> =
2845 (0 .. y.len()).map(|_| Vec::new()).collect();
2846 Chunks::new(z.into_iter().map(|c| c.into()), y.len())
2847 .for_each(|chunk| {
2848 cells.iter_mut().zip(chunk)
2849 .for_each(|(cell, c)| { cell.push(c); });
2850 });
2851 Self { x, y, z: cells, opts: Vec::new() }
2852 }
2853}
2854
2855pub fn colorplot<X, XE, Y, YE, I, J, C>(x: X, y: Y, z: I) -> Colorplot
2857where
2858 X: IntoIterator<Item = XE>,
2859 XE: Real,
2860 Y: IntoIterator<Item = YE>,
2861 YE: Real,
2862 I: IntoIterator<Item = J>,
2863 J: IntoIterator<Item = C>,
2864 C: Into<ColorCell>,
2865{
2866 Colorplot::new(x, y, z)
2867}
2868
2869pub fn colorplot_flat<X, XE, Y, YE, Z, C>(x: X, y: Y, z: Z) -> Colorplot
2872where
2873 X: IntoIterator<Item = XE>,
2874 XE: Real,
2875 Y: IntoIterator<Item = YE>,
2876 YE: Real,
2877 Z: IntoIterator<Item = C>,
2878 C: Into<ColorCell>,
2879{
2880 Colorplot::new_flat(x, y, z)
2881}
2882
2883pub fn colorplot_flat_c<X, XE, Y, YE, Z, C>(x: X, y: Y, z: Z) -> Colorplot
2886where
2887 X: IntoIterator<Item = XE>,
2888 XE: Real,
2889 Y: IntoIterator<Item = YE>,
2890 YE: Real,
2891 Z: IntoIterator<Item = C>,
2892 C: Into<ColorCell>,
2893{
2894 Colorplot::new_flat_c(x, y, z)
2895}
2896
2897impl Matplotlib for Colorplot {
2898 fn is_prelude(&self) -> bool { false }
2899
2900 fn data(&self) -> Option<Value> {
2901 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
2902 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
2903 let z: Vec<Value> =
2904 self.z.iter()
2905 .map(|row| {
2906 let row: Vec<Value> =
2907 row.iter().copied().map(Value::from).collect();
2908 Value::Array(row)
2909 })
2910 .collect();
2911 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
2912 }
2913
2914 fn py_cmd(&self) -> String {
2915 format!("\
2916_dx = (data[0][1] - data[0][0], data[0][-1] - data[0][-2])
2917_dy = (data[1][1] - data[1][0], data[1][-1] - data[1][-2])
2918_extent = [
2919 data[0][0] - _dx[0] / 2.0, data[0][-1] + _dx[1] / 2.0,
2920 data[1][0] - _dy[0] / 2.0, data[1][-1] + _dy[1] / 2.0,
2921]
2922_opts = dict(interpolation=\"nearest\") | dict({})
2923im = mimage.NonUniformImage(ax, extent=_extent, **_opts)
2924im.set_data(data[0], data[1], data[2])
2925ax.add_image(im)
2926ax.set_xlim(_extent[0], _extent[1])
2927ax.set_ylim(_extent[2], _extent[3])
2928del _dx, _dy, _extent, _opts",
2929 self.opts.as_py(),
2930 )
2931 }
2932}
2933
2934impl MatplotlibOpts for Colorplot {
2935 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2936 self.opts.push((key, val).into());
2937 self
2938 }
2939}
2940
2941#[derive(Clone, Debug, PartialEq)]
2951pub struct FillBetween {
2952 pub x: Vec<f64>,
2954 pub y1: Vec<f64>,
2956 pub y2: Vec<f64>,
2958 pub opts: Vec<Opt>,
2960}
2961
2962impl FillBetween {
2963 pub fn new<X, XE, Y1, Y1E, Y2, Y2E>(x: X, y1: Y1, y2: Y2) -> Self
2965 where
2966 X: IntoIterator<Item = XE>,
2967 XE: Real,
2968 Y1: IntoIterator<Item = Y1E>,
2969 Y1E: Real,
2970 Y2: IntoIterator<Item = Y2E>,
2971 Y2E: Real,
2972 {
2973 Self {
2974 x: x.into_iter().map(Real::into_f64).collect(),
2975 y1: y1.into_iter().map(Real::into_f64).collect(),
2976 y2: y2.into_iter().map(Real::into_f64).collect(),
2977 opts: Vec::new(),
2978 }
2979 }
2980
2981 pub fn new_data<I, XE, Y1E, Y2E>(data: I) -> Self
2983 where
2984 I: IntoIterator<Item = (XE, Y1E, Y2E)>,
2985 XE: Real,
2986 Y1E: Real,
2987 Y2E: Real,
2988 {
2989 let ((x, y1), y2) =
2990 data.into_iter()
2991 .map(|(a, b, c)| (a.into_f64(), b.into_f64(), c.into_f64()))
2992 .map(assoc)
2993 .unzip();
2994 Self { x, y1, y2, opts: Vec::new() }
2995 }
2996}
2997
2998pub fn fill_between<X, XE, Y1, Y1E, Y2, Y2E>(
3000 x: X,
3001 y1: Y1,
3002 y2: Y2,
3003) -> FillBetween
3004where
3005 X: IntoIterator<Item = XE>,
3006 XE: Real,
3007 Y1: IntoIterator<Item = Y1E>,
3008 Y1E: Real,
3009 Y2: IntoIterator<Item = Y2E>,
3010 Y2E: Real,
3011{
3012 FillBetween::new(x, y1, y2)
3013}
3014
3015pub fn fill_between_data<I, XE, Y1E, Y2E>(data: I) -> FillBetween
3017where
3018 I: IntoIterator<Item = (XE, Y1E, Y2E)>,
3019 XE: Real,
3020 Y1E: Real,
3021 Y2E: Real,
3022{
3023 FillBetween::new_data(data)
3024}
3025
3026impl Matplotlib for FillBetween {
3027 fn is_prelude(&self) -> bool { false }
3028
3029 fn data(&self) -> Option<Value> {
3030 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
3031 let y1: Vec<Value> = self.y1.iter().copied().map(Value::from).collect();
3032 let y2: Vec<Value> = self.y2.iter().copied().map(Value::from).collect();
3033 Some(Value::Array(vec![x.into(), y1.into(), y2.into()]))
3034 }
3035
3036 fn py_cmd(&self) -> String {
3037 format!("ax.fill_between(data[0], data[1], data[2]{}{})",
3038 if self.opts.is_empty() { "" } else { ", " },
3039 self.opts.as_py(),
3040 )
3041 }
3042}
3043
3044impl MatplotlibOpts for FillBetween {
3045 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3046 self.opts.push((key, val).into());
3047 self
3048 }
3049}
3050
3051impl From<Errorbar> for FillBetween {
3053 fn from(errorbar: Errorbar) -> Self {
3054 let Errorbar { x, mut y, mut e, opts } = errorbar;
3055 y.iter_mut()
3056 .zip(e.iter_mut())
3057 .for_each(|(yk, ek)| {
3058 let y = *yk;
3059 let e = *ek;
3060 *yk -= e;
3061 *ek += y;
3062 });
3063 Self { x, y1: y, y2: e, opts }
3064 }
3065}
3066
3067impl From<Errorbar2> for FillBetween {
3069 fn from(errorbar2: Errorbar2) -> Self {
3070 let Errorbar2 { x, mut y, mut e_neg, e_pos, opts } = errorbar2;
3071 y.iter_mut()
3072 .zip(e_neg.iter_mut().zip(e_pos.iter()))
3073 .for_each(|(yk, (emk, epk))| {
3074 let y = *yk;
3075 let em = *emk;
3076 let ep = *epk;
3077 *yk -= em;
3078 *emk = y + ep;
3079 });
3080 Self { x, y1: y, y2: e_neg, opts }
3081 }
3082}
3083
3084#[derive(Clone, Debug, PartialEq)]
3094pub struct FillBetweenX {
3095 pub y: Vec<f64>,
3097 pub x1: Vec<f64>,
3099 pub x2: Vec<f64>,
3101 pub opts: Vec<Opt>,
3103}
3104
3105impl FillBetweenX {
3106 pub fn new<Y, YE, X1, X1E, X2, X2E>(y: Y, x1: X1, x2: X2) -> Self
3108 where
3109 Y: IntoIterator<Item = YE>,
3110 YE: Real,
3111 X1: IntoIterator<Item = X1E>,
3112 X1E: Real,
3113 X2: IntoIterator<Item = X2E>,
3114 X2E: Real,
3115 {
3116 Self {
3117 y: y.into_iter().map(Real::into_f64).collect(),
3118 x1: x1.into_iter().map(Real::into_f64).collect(),
3119 x2: x2.into_iter().map(Real::into_f64).collect(),
3120 opts: Vec::new(),
3121 }
3122 }
3123
3124 pub fn new_data<I, YE, X1E, X2E>(data: I) -> Self
3126 where
3127 I: IntoIterator<Item = (YE, X1E, X2E)>,
3128 YE: Real,
3129 X1E: Real,
3130 X2E: Real,
3131 {
3132 let ((y, x1), x2) =
3133 data.into_iter()
3134 .map(|(a, b, c)| (a.into_f64(), b.into_f64(), c.into_f64()))
3135 .map(assoc)
3136 .unzip();
3137 Self { y, x1, x2, opts: Vec::new() }
3138 }
3139}
3140
3141pub fn fill_betweenx<Y, YE, X1, X1E, X2, X2E>(
3143 y: Y,
3144 x1: X1,
3145 x2: X2,
3146) -> FillBetweenX
3147where
3148 Y: IntoIterator<Item = YE>,
3149 YE: Real,
3150 X1: IntoIterator<Item = X1E>,
3151 X1E: Real,
3152 X2: IntoIterator<Item = X2E>,
3153 X2E: Real,
3154{
3155 FillBetweenX::new(y, x1, x2)
3156}
3157
3158pub fn fill_betweenx_data<I, YE, X1E, X2E>(data: I) -> FillBetweenX
3160where
3161 I: IntoIterator<Item = (YE, X1E, X2E)>,
3162 YE: Real,
3163 X1E: Real,
3164 X2E: Real,
3165{
3166 FillBetweenX::new_data(data)
3167}
3168
3169impl Matplotlib for FillBetweenX {
3170 fn is_prelude(&self) -> bool { false }
3171
3172 fn data(&self) -> Option<Value> {
3173 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
3174 let x1: Vec<Value> = self.x1.iter().copied().map(Value::from).collect();
3175 let x2: Vec<Value> = self.x2.iter().copied().map(Value::from).collect();
3176 Some(Value::Array(vec![y.into(), x1.into(), x2.into()]))
3177 }
3178
3179 fn py_cmd(&self) -> String {
3180 format!("ax.fill_betweenx(data[0], data[1], data[2]{}{})",
3181 if self.opts.is_empty() { "" } else { ", " },
3182 self.opts.as_py(),
3183 )
3184 }
3185}
3186
3187impl MatplotlibOpts for FillBetweenX {
3188 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3189 self.opts.push((key, val).into());
3190 self
3191 }
3192}
3193
3194#[derive(Clone, Debug, PartialEq)]
3204pub struct AxHLine {
3205 pub y: f64,
3207 pub opts: Vec<Opt>,
3209}
3210
3211impl AxHLine {
3212 pub fn new(y: f64) -> Self {
3214 Self { y, opts: Vec::new() }
3215 }
3216}
3217
3218pub fn axhline(y: f64) -> AxHLine { AxHLine::new(y) }
3220
3221impl Matplotlib for AxHLine {
3222 fn is_prelude(&self) -> bool { false }
3223
3224 fn data(&self) -> Option<Value> { None }
3225
3226 fn py_cmd(&self) -> String {
3227 format!("ax.axhline({}{}{})",
3228 self.y.as_py(),
3229 if self.opts.is_empty() { "" } else { ", " },
3230 self.opts.as_py(),
3231 )
3232 }
3233}
3234
3235impl MatplotlibOpts for AxHLine {
3236 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3237 self.opts.push((key, val).into());
3238 self
3239 }
3240}
3241
3242#[derive(Clone, Debug, PartialEq)]
3252pub struct AxVLine {
3253 pub x: f64,
3255 pub opts: Vec<Opt>,
3257}
3258
3259impl AxVLine {
3260 pub fn new(x: f64) -> Self {
3262 Self { x, opts: Vec::new() }
3263 }
3264}
3265
3266pub fn axvline(x: f64) -> AxVLine { AxVLine::new(x) }
3268
3269impl Matplotlib for AxVLine {
3270 fn is_prelude(&self) -> bool { false }
3271
3272 fn data(&self) -> Option<Value> { None }
3273
3274 fn py_cmd(&self) -> String {
3275 format!("ax.axvline({}{}{})",
3276 self.x.as_py(),
3277 if self.opts.is_empty() { "" } else { ", " },
3278 self.opts.as_py(),
3279 )
3280 }
3281}
3282
3283impl MatplotlibOpts for AxVLine {
3284 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3285 self.opts.push((key, val).into());
3286 self
3287 }
3288}
3289
3290#[derive(Clone, Debug, PartialEq)]
3296pub struct AxLine {
3297 pub xy1: (f64, f64),
3299 pub xy2: (f64, f64),
3301 pub opts: Vec<Opt>,
3303}
3304
3305impl AxLine {
3306 pub fn new(xy1: (f64, f64), xy2: (f64, f64)) -> Self {
3308 Self { xy1, xy2, opts: Vec::new() }
3309 }
3310}
3311
3312pub fn axline(xy1: (f64, f64), xy2: (f64, f64)) -> AxLine {
3314 AxLine::new(xy1, xy2)
3315}
3316
3317impl Matplotlib for AxLine {
3318 fn is_prelude(&self) -> bool { false }
3319
3320 fn data(&self) -> Option<Value> { None }
3321
3322 fn py_cmd(&self) -> String {
3323 format!("ax.axline({}, {}{}{})",
3324 self.xy1.as_py(),
3325 self.xy2.as_py(),
3326 if self.opts.is_empty() { "" } else { ", " },
3327 self.opts.as_py(),
3328 )
3329 }
3330}
3331
3332impl MatplotlibOpts for AxLine {
3333 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3334 self.opts.push((key, val).into());
3335 self
3336 }
3337}
3338
3339#[derive(Clone, Debug, PartialEq)]
3345pub struct AxLineM {
3346 pub xy: (f64, f64),
3348 pub m: f64,
3350 pub opts: Vec<Opt>,
3352}
3353
3354impl AxLineM {
3355 pub fn new(xy: (f64, f64), m: f64) -> Self {
3357 Self { xy, m, opts: Vec::new() }
3358 }
3359}
3360
3361pub fn axlinem(xy: (f64, f64), m: f64) -> AxLineM { AxLineM::new(xy, m) }
3363
3364impl Matplotlib for AxLineM {
3365 fn is_prelude(&self) -> bool { false }
3366
3367 fn data(&self) -> Option<Value> { None }
3368
3369 fn py_cmd(&self) -> String {
3370 format!("ax.axline({}, xy2=None, slope={}{}{})",
3371 self.xy.as_py(),
3372 self.m.as_py(),
3373 if self.opts.is_empty() { "" } else { ", " },
3374 self.opts.as_py(),
3375 )
3376 }
3377}
3378
3379impl MatplotlibOpts for AxLineM {
3380 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3381 self.opts.push((key, val).into());
3382 self
3383 }
3384}
3385
3386#[derive(Clone, Debug, PartialEq)]
3396pub struct Pie {
3397 pub data: Vec<f64>,
3399 pub opts: Vec<Opt>,
3401}
3402
3403impl Pie {
3404 pub fn new<I, E>(data: I) -> Self
3406 where
3407 I: IntoIterator<Item = E>,
3408 E: Real,
3409 {
3410 Self {
3411 data: data.into_iter().map(Real::into_f64).collect(),
3412 opts: Vec::new(),
3413 }
3414 }
3415}
3416
3417pub fn pie<I, E>(data: I) -> Pie
3419where
3420 I: IntoIterator<Item = E>,
3421 E: Real,
3422{
3423 Pie::new(data)
3424}
3425
3426impl Matplotlib for Pie {
3427 fn is_prelude(&self) -> bool { false }
3428
3429 fn data(&self) -> Option<Value> {
3430 Some(Value::Array(
3431 self.data.iter().copied().map(Value::from).collect()))
3432 }
3433
3434 fn py_cmd(&self) -> String {
3435 format!("ax.pie(data{}{})",
3436 if self.opts.is_empty() { "" } else { ", " },
3437 self.opts.as_py(),
3438 )
3439 }
3440}
3441
3442impl MatplotlibOpts for Pie {
3443 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3444 self.opts.push((key, val).into());
3445 self
3446 }
3447}
3448
3449#[derive(Clone, Debug, PartialEq)]
3461pub struct Text {
3462 pub x: f64,
3464 pub y: f64,
3466 pub s: String,
3468 pub opts: Vec<Opt>,
3470}
3471
3472impl Text {
3473 pub fn new(x: f64, y: f64, s: &str) -> Self {
3475 Self { x, y, s: s.into(), opts: Vec::new() }
3476 }
3477}
3478
3479pub fn text(x: f64, y: f64, s: &str) -> Text { Text::new(x, y, s) }
3481
3482impl Matplotlib for Text {
3483 fn is_prelude(&self) -> bool { false }
3484
3485 fn data(&self) -> Option<Value> {
3486 Some(Value::Array(vec![
3487 self.x.into(),
3488 self.y.into(),
3489 (&*self.s).into(),
3490 ]))
3491 }
3492
3493 fn py_cmd(&self) -> String {
3494 format!("ax.text(data[0], data[1], data[2]{}{})",
3495 if self.opts.is_empty() { "" } else { ", " },
3496 self.opts.as_py(),
3497 )
3498 }
3499}
3500
3501impl MatplotlibOpts for Text {
3502 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3503 self.opts.push((key, val).into());
3504 self
3505 }
3506}
3507
3508#[derive(Clone, Debug, PartialEq)]
3518pub struct AxText {
3519 pub x: f64,
3521 pub y: f64,
3523 pub s: String,
3525 pub opts: Vec<Opt>,
3527}
3528
3529impl AxText {
3530 pub fn new(x: f64, y: f64, s: &str) -> Self {
3532 Self { x, y, s: s.into(), opts: Vec::new() }
3533 }
3534}
3535
3536pub fn axtext(x: f64, y: f64, s: &str) -> AxText { AxText::new(x, y, s) }
3538
3539impl Matplotlib for AxText {
3540 fn is_prelude(&self) -> bool { false }
3541
3542 fn data(&self) -> Option<Value> {
3543 Some(Value::Array(vec![
3544 self.x.into(),
3545 self.y.into(),
3546 (&*self.s).into(),
3547 ]))
3548 }
3549
3550 fn py_cmd(&self) -> String {
3551 format!(
3552 "ax.text(data[0], data[1], data[2], transform=ax.transAxes{}{})",
3553 if self.opts.is_empty() { "" } else { ", " },
3554 self.opts.as_py(),
3555 )
3556 }
3557}
3558
3559impl MatplotlibOpts for AxText {
3560 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3561 self.opts.push((key, val).into());
3562 self
3563 }
3564}
3565
3566#[derive(Clone, Debug, PartialEq)]
3579pub struct FigText {
3580 pub x: f64,
3582 pub y: f64,
3584 pub s: String,
3586 pub opts: Vec<Opt>,
3588}
3589
3590impl FigText {
3591 pub fn new(x: f64, y: f64, s: &str) -> Self {
3593 Self { x, y, s: s.into(), opts: Vec::new() }
3594 }
3595}
3596
3597pub fn figtext(x: f64, y: f64, s: &str) -> FigText { FigText::new(x, y, s) }
3599
3600impl Matplotlib for FigText {
3601 fn is_prelude(&self) -> bool { false }
3602
3603 fn data(&self) -> Option<Value> {
3604 Some(Value::Array(vec![
3605 self.x.into(),
3606 self.y.into(),
3607 (&*self.s).into(),
3608 ]))
3609 }
3610
3611 fn py_cmd(&self) -> String {
3612 format!("fig.text(data[0], data[1], data[2]{}{})",
3613 if self.opts.is_empty() { "" } else { ", " },
3614 self.opts.as_py(),
3615 )
3616 }
3617}
3618
3619impl MatplotlibOpts for FigText {
3620 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3621 self.opts.push((key, val).into());
3622 self
3623 }
3624}
3625
3626#[derive(Clone, Debug, PartialEq)]
3641pub struct Colorbar {
3642 pub opts: Vec<Opt>,
3644}
3645
3646impl Default for Colorbar {
3647 fn default() -> Self { Self::new() }
3648}
3649
3650impl Colorbar {
3651 pub fn new() -> Self { Self { opts: Vec::new() } }
3653}
3654
3655pub fn colorbar() -> Colorbar { Colorbar::new() }
3657
3658impl Matplotlib for Colorbar {
3659 fn is_prelude(&self) -> bool { false }
3660
3661 fn data(&self) -> Option<Value> { None }
3662
3663 fn py_cmd(&self) -> String {
3664 format!("cbar = fig.colorbar(im, ax=ax{}{})",
3665 if self.opts.is_empty() { "" } else { ", " },
3666 self.opts.as_py(),
3667 )
3668 }
3669}
3670
3671impl MatplotlibOpts for Colorbar {
3672 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3673 self.opts.push((key, val).into());
3674 self
3675 }
3676}
3677
3678#[derive(Copy, Clone, Debug, PartialEq, Eq)]
3688pub struct Scale {
3689 pub axis: Axis,
3691 pub scale: AxisScale,
3693}
3694
3695impl Scale {
3696 pub fn new(axis: Axis, scale: AxisScale) -> Self { Self { axis, scale } }
3698}
3699
3700pub fn scale(axis: Axis, scale: AxisScale) -> Scale { Scale::new(axis, scale) }
3702
3703pub fn xscale(scale: AxisScale) -> Scale { Scale::new(Axis::X, scale) }
3705
3706pub fn yscale(scale: AxisScale) -> Scale { Scale::new(Axis::Y, scale) }
3708
3709pub fn zscale(scale: AxisScale) -> Scale { Scale::new(Axis::Z, scale) }
3711
3712impl Matplotlib for Scale {
3713 fn is_prelude(&self) -> bool { false }
3714
3715 fn data(&self) -> Option<Value> { None }
3716
3717 fn py_cmd(&self) -> String {
3718 let ax = format!("{:?}", self.axis).to_lowercase();
3719 let sc = format!("{:?}", self.scale).to_lowercase();
3720 format!("ax.set_{}scale(\"{}\")", ax, sc)
3721 }
3722}
3723
3724#[derive(Copy, Clone, Debug, PartialEq, Eq)]
3726pub enum Axis {
3727 X,
3729 Y,
3731 Z,
3733}
3734
3735#[derive(Copy, Clone, Debug, PartialEq, Eq)]
3737pub enum AxisScale {
3738 Linear,
3740 Log,
3742 SymLog,
3746 Logit,
3754}
3755
3756#[derive(Copy, Clone, Debug, PartialEq)]
3766pub struct Lim {
3767 pub axis: Axis,
3769 pub min: Option<f64>,
3773 pub max: Option<f64>,
3777}
3778
3779impl Lim {
3780 pub fn new(axis: Axis, min: Option<f64>, max: Option<f64>) -> Self {
3782 Self { axis, min, max }
3783 }
3784}
3785
3786pub fn lim(axis: Axis, min: Option<f64>, max: Option<f64>) -> Lim {
3788 Lim::new(axis, min, max)
3789}
3790
3791pub fn xlim(min: Option<f64>, max: Option<f64>) -> Lim {
3793 Lim::new(Axis::X, min, max)
3794}
3795
3796pub fn ylim(min: Option<f64>, max: Option<f64>) -> Lim {
3798 Lim::new(Axis::Y, min, max)
3799}
3800
3801pub fn zlim(min: Option<f64>, max: Option<f64>) -> Lim {
3803 Lim::new(Axis::Z, min, max)
3804}
3805
3806impl Matplotlib for Lim {
3807 fn is_prelude(&self) -> bool { false }
3808
3809 fn data(&self) -> Option<Value> { None }
3810
3811 fn py_cmd(&self) -> String {
3812 let ax = format!("{:?}", self.axis).to_lowercase();
3813 let min = self.min.as_ref().map(|x| x.as_py()).unwrap_or("None".into());
3814 let max = self.max.as_ref().map(|x| x.as_py()).unwrap_or("None".into());
3815 format!("ax.set_{}lim({}, {})", ax, min, max)
3816 }
3817}
3818
3819#[derive(Copy, Clone, Debug, PartialEq)]
3831pub struct CLim {
3832 pub min: Option<f64>,
3836 pub max: Option<f64>,
3840}
3841
3842impl CLim {
3843 pub fn new(min: Option<f64>, max: Option<f64>) -> Self {
3845 Self { min, max }
3846 }
3847}
3848
3849pub fn clim(min: Option<f64>, max: Option<f64>) -> CLim { CLim::new(min, max) }
3851
3852impl Matplotlib for CLim {
3853 fn is_prelude(&self) -> bool { false }
3854
3855 fn data(&self) -> Option<Value> { None }
3856
3857 fn py_cmd(&self) -> String {
3858 let min = self.min.as_ref().map(|x| x.as_py()).unwrap_or("None".into());
3859 let max = self.max.as_ref().map(|x| x.as_py()).unwrap_or("None".into());
3860 format!("im.set_clim({}, {})", min, max)
3861 }
3862}
3863
3864#[derive(Clone, Debug, PartialEq)]
3874pub struct Title {
3875 pub s: String,
3877 pub opts: Vec<Opt>,
3879}
3880
3881impl Title {
3882 pub fn new(s: &str) -> Self {
3884 Self { s: s.into(), opts: Vec::new() }
3885 }
3886}
3887
3888pub fn title(s: &str) -> Title { Title::new(s) }
3890
3891impl Matplotlib for Title {
3892 fn is_prelude(&self) -> bool { false }
3893
3894 fn data(&self) -> Option<Value> { None }
3895
3896 fn py_cmd(&self) -> String {
3897 format!("ax.set_title({}{}{})",
3898 self.s.as_py(),
3899 if self.opts.is_empty() { "" } else { ", " },
3900 self.opts.as_py(),
3901 )
3902 }
3903}
3904
3905impl MatplotlibOpts for Title {
3906 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3907 self.opts.push((key, val).into());
3908 self
3909 }
3910}
3911
3912#[derive(Clone, Debug, PartialEq)]
3922pub struct Label {
3923 pub axis: Axis,
3925 pub s: String,
3927 pub opts: Vec<Opt>,
3929}
3930
3931impl Label {
3932 pub fn new(axis: Axis, s: &str) -> Self {
3934 Self { axis, s: s.into(), opts: Vec::new() }
3935 }
3936}
3937
3938pub fn label(axis: Axis, s: &str) -> Label { Label::new(axis, s) }
3940
3941pub fn xlabel(s: &str) -> Label { Label::new(Axis::X, s) }
3943
3944pub fn ylabel(s: &str) -> Label { Label::new(Axis::Y, s) }
3946
3947pub fn zlabel(s: &str) -> Label { Label::new(Axis::Z, s) }
3949
3950impl Matplotlib for Label {
3951 fn is_prelude(&self) -> bool { false }
3952
3953 fn data(&self) -> Option<Value> { None }
3954
3955 fn py_cmd(&self) -> String {
3956 let ax = format!("{:?}", self.axis).to_lowercase();
3957 format!("ax.set_{}label({}{}{})",
3958 ax,
3959 self.s.as_py(),
3960 if self.opts.is_empty() { "" } else { ", " },
3961 self.opts.as_py(),
3962 )
3963 }
3964}
3965
3966impl MatplotlibOpts for Label {
3967 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3968 self.opts.push((key, val).into());
3969 self
3970 }
3971}
3972
3973#[derive(Clone, Debug, PartialEq)]
3986pub struct CLabel {
3987 pub s: String,
3989 pub opts: Vec<Opt>,
3991}
3992
3993impl CLabel {
3994 pub fn new(s: &str) -> Self {
3996 Self { s: s.into(), opts: Vec::new() }
3997 }
3998}
3999
4000pub fn clabel(s: &str) -> CLabel { CLabel::new(s) }
4002
4003impl Matplotlib for CLabel {
4004 fn is_prelude(&self) -> bool { false }
4005
4006 fn data(&self) -> Option<Value> { None }
4007
4008 fn py_cmd(&self) -> String {
4009 format!("cbar.set_label({}{}{})",
4010 self.s.as_py(),
4011 if self.opts.is_empty() { "" } else { ", " },
4012 self.opts.as_py(),
4013 )
4014 }
4015}
4016
4017impl MatplotlibOpts for CLabel {
4018 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4019 self.opts.push((key, val).into());
4020 self
4021 }
4022}
4023
4024#[derive(Clone, Debug, PartialEq)]
4034pub struct Ticks {
4035 pub axis: Axis,
4037 pub v: Vec<f64>,
4039 pub opts: Vec<Opt>,
4041}
4042
4043impl Ticks {
4044 pub fn new<I, VE>(axis: Axis, v: I) -> Self
4046 where
4047 I: IntoIterator<Item = VE>,
4048 VE: Real,
4049 {
4050 Self {
4051 axis,
4052 v: v.into_iter().map(Real::into_f64).collect(),
4053 opts: Vec::new(),
4054 }
4055 }
4056}
4057
4058pub fn ticks<I, VE>(axis: Axis, v: I) -> Ticks
4060where
4061 I: IntoIterator<Item = VE>,
4062 VE: Real,
4063{
4064 Ticks::new(axis, v)
4065}
4066
4067pub fn xticks<I, VE>(v: I) -> Ticks
4069where
4070 I: IntoIterator<Item = VE>,
4071 VE: Real,
4072{
4073 Ticks::new(Axis::X, v)
4074}
4075
4076pub fn yticks<I, VE>(v: I) -> Ticks
4078where
4079 I: IntoIterator<Item = VE>,
4080 VE: Real,
4081{
4082 Ticks::new(Axis::Y, v)
4083}
4084
4085pub fn zticks<I, VE>(v: I) -> Ticks
4087where
4088 I: IntoIterator<Item = VE>,
4089 VE: Real,
4090{
4091 Ticks::new(Axis::Z, v)
4092}
4093
4094impl Matplotlib for Ticks {
4095 fn is_prelude(&self) -> bool { false }
4096
4097 fn data(&self) -> Option<Value> {
4098 let v: Vec<Value> = self.v.iter().copied().map(Value::from).collect();
4099 Some(Value::Array(v))
4100 }
4101
4102 fn py_cmd(&self) -> String {
4103 format!("ax.set_{}ticks(data{}{})",
4104 format!("{:?}", self.axis).to_lowercase(),
4105 if self.opts.is_empty() { "" } else { ", " },
4106 self.opts.as_py(),
4107 )
4108 }
4109}
4110
4111impl MatplotlibOpts for Ticks {
4112 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4113 self.opts.push((key, val).into());
4114 self
4115 }
4116}
4117
4118#[derive(Clone, Debug, PartialEq)]
4131pub struct CTicks {
4132 pub v: Vec<f64>,
4134 pub opts: Vec<Opt>,
4136}
4137
4138impl CTicks {
4139 pub fn new<I, VE>(v: I) -> Self
4141 where
4142 I: IntoIterator<Item = VE>,
4143 VE: Real,
4144 {
4145 Self {
4146 v: v.into_iter().map(Real::into_f64).collect(),
4147 opts: Vec::new(),
4148 }
4149 }
4150}
4151
4152pub fn cticks<I, VE>(v: I) -> CTicks
4154where
4155 I: IntoIterator<Item = VE>,
4156 VE: Real,
4157{
4158 CTicks::new(v)
4159}
4160
4161impl Matplotlib for CTicks {
4162 fn is_prelude(&self) -> bool { false }
4163
4164 fn data(&self) -> Option<Value> {
4165 let v: Vec<Value> = self.v.iter().copied().map(Value::from).collect();
4166 Some(Value::Array(v))
4167 }
4168
4169 fn py_cmd(&self) -> String {
4170 format!("cbar.set_ticks(data{}{})",
4171 if self.opts.is_empty() { "" } else { ", " },
4172 self.opts.as_py(),
4173 )
4174 }
4175}
4176
4177impl MatplotlibOpts for CTicks {
4178 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4179 self.opts.push((key, val).into());
4180 self
4181 }
4182}
4183
4184#[derive(Clone, Debug, PartialEq)]
4194pub struct TickLabels {
4195 pub axis: Axis,
4197 pub v: Vec<f64>,
4199 pub s: Vec<String>,
4201 pub opts: Vec<Opt>,
4203}
4204
4205impl TickLabels {
4206 pub fn new<I, VE, J, S>(axis: Axis, v: I, s: J) -> Self
4208 where
4209 I: IntoIterator<Item = VE>,
4210 VE: Real,
4211 J: IntoIterator<Item = S>,
4212 S: Into<String>,
4213 {
4214 Self {
4215 axis,
4216 v: v.into_iter().map(Real::into_f64).collect(),
4217 s: s.into_iter().map(|sk| sk.into()).collect(),
4218 opts: Vec::new(),
4219 }
4220 }
4221
4222 pub fn new_data<I, VE, S>(axis: Axis, ticklabels: I) -> Self
4224 where
4225 I: IntoIterator<Item = (VE, S)>,
4226 VE: Real,
4227 S: Into<String>,
4228 {
4229 let (v, s): (Vec<f64>, Vec<String>) =
4230 ticklabels.into_iter()
4231 .map(|(vk, sk)| (vk.into_f64(), sk.into()))
4232 .unzip();
4233 Self { axis, v, s, opts: Vec::new() }
4234 }
4235}
4236
4237pub fn ticklabels<I, VE, J, S>(axis: Axis, v: I, s: J) -> TickLabels
4239where
4240 I: IntoIterator<Item = VE>,
4241 VE: Real,
4242 J: IntoIterator<Item = S>,
4243 S: Into<String>,
4244{
4245 TickLabels::new(axis, v, s)
4246}
4247
4248pub fn ticklabels_data<I, VE, S>(axis: Axis, ticklabels: I) -> TickLabels
4250where
4251 I: IntoIterator<Item = (VE, S)>,
4252 VE: Real,
4253 S: Into<String>,
4254{
4255 TickLabels::new_data(axis, ticklabels)
4256}
4257
4258pub fn xticklabels<I, VE, J, S>(v: I, s: J) -> TickLabels
4260where
4261 I: IntoIterator<Item = VE>,
4262 VE: Real,
4263 J: IntoIterator<Item = S>,
4264 S: Into<String>,
4265{
4266 TickLabels::new(Axis::X, v, s)
4267}
4268
4269pub fn xticklabels_data<I, VE, S>(ticklabels: I) -> TickLabels
4272where
4273 I: IntoIterator<Item = (VE, S)>,
4274 VE: Real,
4275 S: Into<String>,
4276{
4277 TickLabels::new_data(Axis::X, ticklabels)
4278}
4279
4280pub fn yticklabels<I, VE, J, S>(v: I, s: J) -> TickLabels
4282where
4283 I: IntoIterator<Item = VE>,
4284 VE: Real,
4285 J: IntoIterator<Item = S>,
4286 S: Into<String>,
4287{
4288 TickLabels::new(Axis::Y, v, s)
4289}
4290
4291pub fn yticklabels_data<I, VE, S>(ticklabels: I) -> TickLabels
4294where
4295 I: IntoIterator<Item = (VE, S)>,
4296 VE: Real,
4297 S: Into<String>,
4298{
4299 TickLabels::new_data(Axis::Y, ticklabels)
4300}
4301
4302pub fn zticklabels<I, VE, J, S>(v: I, s: J) -> TickLabels
4304where
4305 I: IntoIterator<Item = VE>,
4306 VE: Real,
4307 J: IntoIterator<Item = S>,
4308 S: Into<String>,
4309{
4310 TickLabels::new(Axis::Z, v, s)
4311}
4312
4313pub fn zticklabels_data<I, VE, S>(ticklabels: I) -> TickLabels
4316where
4317 I: IntoIterator<Item = (VE, S)>,
4318 VE: Real,
4319 S: Into<String>,
4320{
4321 TickLabels::new_data(Axis::Z, ticklabels)
4322}
4323
4324impl Matplotlib for TickLabels {
4325 fn is_prelude(&self) -> bool { false }
4326
4327 fn data(&self) -> Option<Value> {
4328 let v: Vec<Value> = self.v.iter().copied().map(Value::from).collect();
4329 let s: Vec<Value> = self.s.iter().cloned().map(Value::from).collect();
4330 Some(Value::Array(vec![v.into(), s.into()]))
4331 }
4332
4333 fn py_cmd(&self) -> String {
4334 format!("ax.set_{}ticks(data[0], labels=data[1]{}{})",
4335 format!("{:?}", self.axis).to_lowercase(),
4336 if self.opts.is_empty() { "" } else { ", " },
4337 self.opts.as_py(),
4338 )
4339 }
4340}
4341
4342impl MatplotlibOpts for TickLabels {
4343 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4344 self.opts.push((key, val).into());
4345 self
4346 }
4347}
4348
4349#[derive(Clone, Debug, PartialEq)]
4362pub struct CTickLabels {
4363 pub v: Vec<f64>,
4365 pub s: Vec<String>,
4367 pub opts: Vec<Opt>,
4369}
4370
4371impl CTickLabels {
4372 pub fn new<I, VE, J, S>(v: I, s: J) -> Self
4374 where
4375 I: IntoIterator<Item = VE>,
4376 VE: Real,
4377 J: IntoIterator<Item = S>,
4378 S: Into<String>,
4379 {
4380 Self {
4381 v: v.into_iter().map(Real::into_f64).collect(),
4382 s: s.into_iter().map(|sk| sk.into()).collect(),
4383 opts: Vec::new(),
4384 }
4385 }
4386
4387 pub fn new_data<I, VE, S>(ticklabels: I) -> Self
4389 where
4390 I: IntoIterator<Item = (VE, S)>,
4391 VE: Real,
4392 S: Into<String>,
4393 {
4394 let (v, s): (Vec<f64>, Vec<String>) =
4395 ticklabels.into_iter()
4396 .map(|(vk, sk)| (vk.into_f64(), sk.into()))
4397 .unzip();
4398 Self { v, s, opts: Vec::new() }
4399 }
4400}
4401
4402pub fn cticklabels<I, VE, J, S>(v: I, s: J) -> CTickLabels
4404where
4405 I: IntoIterator<Item = VE>,
4406 VE: Real,
4407 J: IntoIterator<Item = S>,
4408 S: Into<String>,
4409{
4410 CTickLabels::new(v, s)
4411}
4412
4413pub fn cticklabels_data<I, VE, S>(ticklabels: I) -> CTickLabels
4415where
4416 I: IntoIterator<Item = (VE, S)>,
4417 VE: Real,
4418 S: Into<String>,
4419{
4420 CTickLabels::new_data(ticklabels)
4421}
4422
4423impl Matplotlib for CTickLabels {
4424 fn is_prelude(&self) -> bool { false }
4425
4426 fn data(&self) -> Option<Value> {
4427 let v: Vec<Value> = self.v.iter().copied().map(Value::from).collect();
4428 let s: Vec<Value> = self.s.iter().cloned().map(Value::from).collect();
4429 Some(Value::Array(vec![v.into(), s.into()]))
4430 }
4431
4432 fn py_cmd(&self) -> String {
4433 format!("cbar.set_ticks(data[0], labels=data[1]{}{})",
4434 if self.opts.is_empty() { "" } else { ", " },
4435 self.opts.as_py(),
4436 )
4437 }
4438}
4439
4440impl MatplotlibOpts for CTickLabels {
4441 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4442 self.opts.push((key, val).into());
4443 self
4444 }
4445}
4446
4447#[derive(Clone, Debug, PartialEq)]
4457pub struct TickParams {
4458 pub axis: Axis2,
4460 pub opts: Vec<Opt>,
4462}
4463
4464impl TickParams {
4465 pub fn new(axis: Axis2) -> Self {
4467 Self { axis, opts: Vec::new() }
4468 }
4469}
4470
4471pub fn tick_params(axis: Axis2) -> TickParams { TickParams::new(axis) }
4473
4474pub fn xtick_params() -> TickParams { TickParams::new(Axis2::X) }
4476
4477pub fn ytick_params() -> TickParams { TickParams::new(Axis2::Y) }
4479
4480impl Matplotlib for TickParams {
4481 fn is_prelude(&self) -> bool { false }
4482
4483 fn data(&self) -> Option<Value> { None }
4484
4485 fn py_cmd(&self) -> String {
4486 format!("ax.tick_params(\"{}\"{}{})",
4487 format!("{:?}", self.axis).to_lowercase(),
4488 if self.opts.is_empty() { "" } else { ", " },
4489 self.opts.as_py(),
4490 )
4491 }
4492}
4493
4494impl MatplotlibOpts for TickParams {
4495 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4496 self.opts.push((key, val).into());
4497 self
4498 }
4499}
4500
4501#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4503pub enum Axis2 {
4504 X,
4506 Y,
4508 Both,
4510}
4511
4512#[derive(Clone, Debug, PartialEq)]
4522pub struct InvertAx {
4523 pub axis: Axis,
4525}
4526
4527impl InvertAx {
4528 pub fn new(axis: Axis) -> Self {
4530 Self { axis }
4531 }
4532}
4533
4534pub fn invert_ax(axis: Axis) -> InvertAx { InvertAx::new(axis) }
4536
4537pub fn invert_x() -> InvertAx { InvertAx::new(Axis::X) }
4539
4540pub fn invert_y() -> InvertAx { InvertAx::new(Axis::Y) }
4542
4543pub fn invert_z() -> InvertAx { InvertAx::new(Axis::Z) }
4545
4546impl Matplotlib for InvertAx {
4547 fn is_prelude(&self) -> bool { false }
4548
4549 fn data(&self) -> Option<Value> { None }
4550
4551 fn py_cmd(&self) -> String {
4552 let ax = format!("{:?}", self.axis).to_lowercase();
4553 format!("ax.invert_{}axis()", ax)
4554 }
4555}
4556
4557#[derive(Clone, Debug, PartialEq)]
4567pub struct Aspect {
4568 pub asp: f64,
4570 pub opts: Vec<Opt>,
4572}
4573
4574impl Aspect {
4575 pub fn new(asp: f64) -> Self {
4577 Self { asp, opts: Vec::new() }
4578 }
4579}
4580
4581pub fn aspect(asp: f64) -> Aspect { Aspect::new(asp) }
4583
4584impl Matplotlib for Aspect {
4585 fn is_prelude(&self) -> bool { false }
4586
4587 fn data(&self) -> Option<Value> { None }
4588
4589 fn py_cmd(&self) -> String {
4590 format!("ax.set_aspect({}{}{})",
4591 self.asp.as_py(),
4592 if self.opts.is_empty() { "" } else { ", " },
4593 self.opts.as_py(),
4594 )
4595 }
4596}
4597
4598impl MatplotlibOpts for Aspect {
4599 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4600 self.opts.push((key, val).into());
4601 self
4602 }
4603}
4604
4605#[derive(Clone, Debug, PartialEq)]
4615pub struct SupTitle {
4616 pub s: String,
4618 pub opts: Vec<Opt>,
4620}
4621
4622impl SupTitle {
4623 pub fn new(s: &str) -> Self {
4625 Self { s: s.into(), opts: Vec::new() }
4626 }
4627}
4628
4629pub fn suptitle(s: &str) -> SupTitle { SupTitle::new(s) }
4631
4632impl Matplotlib for SupTitle {
4633 fn is_prelude(&self) -> bool { false }
4634
4635 fn data(&self) -> Option<Value> { None }
4636
4637 fn py_cmd(&self) -> String {
4638 format!("fig.suptitle({}{}{})",
4639 self.s.as_py(),
4640 if self.opts.is_empty() { "" } else { ", " },
4641 self.opts.as_py(),
4642 )
4643 }
4644}
4645
4646impl MatplotlibOpts for SupTitle {
4647 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4648 self.opts.push((key, val).into());
4649 self
4650 }
4651}
4652
4653#[derive(Clone, Debug, PartialEq)]
4663pub struct SupXLabel {
4664 pub s: String,
4666 pub opts: Vec<Opt>,
4668}
4669
4670impl SupXLabel {
4671 pub fn new(s: &str) -> Self {
4673 Self { s: s.into(), opts: Vec::new() }
4674 }
4675}
4676
4677pub fn supxlabel(s: &str) -> SupXLabel { SupXLabel::new(s) }
4679
4680impl Matplotlib for SupXLabel {
4681 fn is_prelude(&self) -> bool { false }
4682
4683 fn data(&self) -> Option<Value> { None }
4684
4685 fn py_cmd(&self) -> String {
4686 format!("fig.supxlabel({}{}{})",
4687 self.s.as_py(),
4688 if self.opts.is_empty() { "" } else { ", " },
4689 self.opts.as_py(),
4690 )
4691 }
4692}
4693
4694impl MatplotlibOpts for SupXLabel {
4695 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4696 self.opts.push((key, val).into());
4697 self
4698 }
4699}
4700
4701#[derive(Clone, Debug, PartialEq)]
4711pub struct SupYLabel {
4712 pub s: String,
4714 pub opts: Vec<Opt>,
4716}
4717
4718impl SupYLabel {
4719 pub fn new(s: &str) -> Self {
4721 Self { s: s.into(), opts: Vec::new() }
4722 }
4723}
4724
4725pub fn supylabel(s: &str) -> SupYLabel { SupYLabel::new(s) }
4727
4728impl Matplotlib for SupYLabel {
4729 fn is_prelude(&self) -> bool { false }
4730
4731 fn data(&self) -> Option<Value> { None }
4732
4733 fn py_cmd(&self) -> String {
4734 format!("fig.supylabel({}{}{})",
4735 self.s.as_py(),
4736 if self.opts.is_empty() { "" } else { ", " },
4737 self.opts.as_py(),
4738 )
4739 }
4740}
4741
4742impl MatplotlibOpts for SupYLabel {
4743 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4744 self.opts.push((key, val).into());
4745 self
4746 }
4747}
4748
4749#[derive(Clone, Debug, PartialEq)]
4759pub struct Legend {
4760 pub opts: Vec<Opt>,
4762}
4763
4764impl Default for Legend {
4765 fn default() -> Self { Self::new() }
4766}
4767
4768impl Legend {
4769 pub fn new() -> Self {
4771 Self { opts: Vec::new() }
4772 }
4773}
4774
4775pub fn legend() -> Legend { Legend::new() }
4777
4778impl Matplotlib for Legend {
4779 fn is_prelude(&self) -> bool { false }
4780
4781 fn data(&self) -> Option<Value> { None }
4782
4783 fn py_cmd(&self) -> String {
4784 format!("ax.legend({})", self.opts.as_py())
4785 }
4786}
4787
4788impl MatplotlibOpts for Legend {
4789 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4790 self.opts.push((key, val).into());
4791 self
4792 }
4793}
4794
4795#[derive(Clone, Debug, PartialEq)]
4805pub struct Grid {
4806 pub onoff: bool,
4808 pub opts: Vec<Opt>,
4810}
4811
4812impl Grid {
4813 pub fn new(onoff: bool) -> Self { Self { onoff, opts: Vec::new() } }
4815}
4816
4817pub fn grid(onoff: bool) -> Grid { Grid::new(onoff) }
4819
4820impl Matplotlib for Grid {
4821 fn is_prelude(&self) -> bool { false }
4822
4823 fn data(&self) -> Option<Value> { None }
4824
4825 fn py_cmd(&self) -> String {
4826 format!("ax.grid({}{}{})",
4827 self.onoff.as_py(),
4828 if self.opts.is_empty() { "" } else { ", " },
4829 self.opts.as_py(),
4830 )
4831 }
4832}
4833
4834impl MatplotlibOpts for Grid {
4835 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4836 self.opts.push((key, val).into());
4837 self
4838 }
4839}
4840
4841#[derive(Clone, Debug, PartialEq)]
4851pub struct TightLayout {
4852 pub opts: Vec<Opt>,
4854}
4855
4856impl Default for TightLayout {
4857 fn default() -> Self { Self::new() }
4858}
4859
4860impl TightLayout {
4861 pub fn new() -> Self { Self { opts: Vec::new() } }
4863}
4864
4865pub fn tight_layout() -> TightLayout { TightLayout::new() }
4867
4868impl Matplotlib for TightLayout {
4869 fn is_prelude(&self) -> bool { false }
4870
4871 fn data(&self) -> Option<Value> { None }
4872
4873 fn py_cmd(&self) -> String {
4874 format!("fig.tight_layout({})", self.opts.as_py())
4875 }
4876}
4877
4878impl MatplotlibOpts for TightLayout {
4879 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4880 self.opts.push((key, val).into());
4881 self
4882 }
4883}
4884
4885#[derive(Clone, Debug, PartialEq)]
4897pub struct InsetAxes {
4898 pub x: f64,
4900 pub y: f64,
4902 pub w: f64,
4904 pub h: f64,
4906 pub opts: Vec<Opt>,
4908}
4909
4910impl InsetAxes {
4911 pub fn new(x: f64, y: f64, w: f64, h: f64) -> Self {
4913 Self { x, y, w, h, opts: Vec::new() }
4914 }
4915
4916 pub fn new_pairs(xy: (f64, f64), wh: (f64, f64)) -> Self {
4919 Self { x: xy.0, y: xy.1, w: wh.0, h: wh.1, opts: Vec::new() }
4920 }
4921}
4922
4923pub fn inset_axes(x: f64, y: f64, w: f64, h: f64) -> InsetAxes {
4925 InsetAxes::new(x, y, w, h)
4926}
4927
4928pub fn inset_axes_pairs(xy: (f64, f64), wh: (f64, f64)) -> InsetAxes {
4931 InsetAxes::new_pairs(xy, wh)
4932}
4933
4934impl Matplotlib for InsetAxes {
4935 fn is_prelude(&self) -> bool { false }
4936
4937 fn data(&self) -> Option<Value> { None }
4938
4939 fn py_cmd(&self) -> String {
4940 format!("ax = ax.inset_axes([{}, {}, {}, {}]{}{})",
4941 self.x.as_py(),
4942 self.y.as_py(),
4943 self.w.as_py(),
4944 self.h.as_py(),
4945 if self.opts.is_empty() { "" } else { ", " },
4946 self.opts.as_py(),
4947 )
4948 }
4949}
4950
4951impl MatplotlibOpts for InsetAxes {
4952 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4953 self.opts.push((key, val).into());
4954 self
4955 }
4956}
4957
4958#[derive(Clone, Debug, PartialEq)]
4968pub struct Plot3 {
4969 pub x: Vec<f64>,
4971 pub y: Vec<f64>,
4973 pub z: Vec<f64>,
4975 pub opts: Vec<Opt>,
4977}
4978
4979impl Plot3 {
4980 pub fn new<X, XE, Y, YE, Z, ZE>(x: X, y: Y, z: Z) -> Self
4982 where
4983 X: IntoIterator<Item = XE>,
4984 XE: Real,
4985 Y: IntoIterator<Item = YE>,
4986 YE: Real,
4987 Z: IntoIterator<Item = ZE>,
4988 ZE: Real,
4989 {
4990 Self {
4991 x: x.into_iter().map(Real::into_f64).collect(),
4992 y: y.into_iter().map(Real::into_f64).collect(),
4993 z: z.into_iter().map(Real::into_f64).collect(),
4994 opts: Vec::new(),
4995 }
4996 }
4997
4998 pub fn new_data<I, XE, YE, ZE>(data: I) -> Self
5000 where
5001 I: IntoIterator<Item = (XE, YE, ZE)>,
5002 XE: Real,
5003 YE: Real,
5004 ZE: Real,
5005 {
5006 let ((x, y), z) =
5007 data.into_iter()
5008 .map(|(a, b, c)| (a.into_f64(), b.into_f64(), c.into_f64()))
5009 .map(assoc)
5010 .unzip();
5011 Self { x, y, z, opts: Vec::new() }
5012 }
5013}
5014
5015pub fn plot3<X, XE, Y, YE, Z, ZE>(x: X, y: Y, z: Z) -> Plot3
5017where
5018 X: IntoIterator<Item = XE>,
5019 XE: Real,
5020 Y: IntoIterator<Item = YE>,
5021 YE: Real,
5022 Z: IntoIterator<Item = ZE>,
5023 ZE: Real,
5024{
5025 Plot3::new(x, y, z)
5026}
5027
5028pub fn plot3_data<I, XE, YE, ZE>(data: I) -> Plot3
5030where
5031 I: IntoIterator<Item = (XE, YE, ZE)>,
5032 XE: Real,
5033 YE: Real,
5034 ZE: Real,
5035{
5036 Plot3::new_data(data)
5037}
5038
5039impl Matplotlib for Plot3 {
5040 fn is_prelude(&self) -> bool { false }
5041
5042 fn data(&self) -> Option<Value> {
5043 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
5044 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
5045 let z: Vec<Value> = self.z.iter().copied().map(Value::from).collect();
5046 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
5047 }
5048
5049 fn py_cmd(&self) -> String {
5050 format!("ax.plot(data[0], data[1], data[2]{}{})",
5051 if self.opts.is_empty() { "" } else { ", " },
5052 self.opts.as_py(),
5053 )
5054 }
5055}
5056
5057impl MatplotlibOpts for Plot3 {
5058 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
5059 self.opts.push((key, val).into());
5060 self
5061 }
5062}
5063
5064#[derive(Clone, Debug, PartialEq)]
5074pub struct Scatter3 {
5075 pub x: Vec<f64>,
5077 pub y: Vec<f64>,
5079 pub z: Vec<f64>,
5081 pub opts: Vec<Opt>,
5083}
5084
5085impl Scatter3 {
5086 pub fn new<X, XE, Y, YE, Z, ZE>(x: X, y: Y, z: Z) -> Self
5088 where
5089 X: IntoIterator<Item = XE>,
5090 XE: Real,
5091 Y: IntoIterator<Item = YE>,
5092 YE: Real,
5093 Z: IntoIterator<Item = ZE>,
5094 ZE: Real,
5095 {
5096 Self {
5097 x: x.into_iter().map(Real::into_f64).collect(),
5098 y: y.into_iter().map(Real::into_f64).collect(),
5099 z: z.into_iter().map(Real::into_f64).collect(),
5100 opts: Vec::new(),
5101 }
5102 }
5103
5104 pub fn new_data<I, XE, YE, ZE>(data: I) -> Self
5106 where
5107 I: IntoIterator<Item = (XE, YE, ZE)>,
5108 XE: Real,
5109 YE: Real,
5110 ZE: Real,
5111 {
5112 let ((x, y), z) =
5113 data.into_iter()
5114 .map(|(a, b, c)| (a.into_f64(), b.into_f64(), c.into_f64()))
5115 .map(assoc)
5116 .unzip();
5117 Self { x, y, z, opts: Vec::new() }
5118 }
5119}
5120
5121pub fn scatter3<X, XE, Y, YE, Z, ZE>(x: X, y: Y, z: Z) -> Scatter3
5123where
5124 X: IntoIterator<Item = XE>,
5125 XE: Real,
5126 Y: IntoIterator<Item = YE>,
5127 YE: Real,
5128 Z: IntoIterator<Item = ZE>,
5129 ZE: Real,
5130{
5131 Scatter3::new(x, y, z)
5132}
5133
5134pub fn scatter3_data<I, XE, YE, ZE>(data: I) -> Scatter3
5136where
5137 I: IntoIterator<Item = (XE, YE, ZE)>,
5138 XE: Real,
5139 YE: Real,
5140 ZE: Real,
5141{
5142 Scatter3::new_data(data)
5143}
5144
5145impl Matplotlib for Scatter3 {
5146 fn is_prelude(&self) -> bool { false }
5147
5148 fn data(&self) -> Option<Value> {
5149 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
5150 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
5151 let z: Vec<Value> = self.z.iter().copied().map(Value::from).collect();
5152 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
5153 }
5154
5155 fn py_cmd(&self) -> String {
5156 format!("ax.scatter(data[0], data[1], data[2]{}{})",
5157 if self.opts.is_empty() { "" } else { ", " },
5158 self.opts.as_py(),
5159 )
5160 }
5161}
5162
5163impl MatplotlibOpts for Scatter3 {
5164 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
5165 self.opts.push((key, val).into());
5166 self
5167 }
5168}
5169
5170#[derive(Clone, Debug, PartialEq)]
5180pub struct Quiver3 {
5181 pub x: Vec<f64>,
5183 pub y: Vec<f64>,
5185 pub z: Vec<f64>,
5187 pub vx: Vec<f64>,
5189 pub vy: Vec<f64>,
5191 pub vz: Vec<f64>,
5193 pub opts: Vec<Opt>,
5195}
5196
5197impl Quiver3 {
5198 pub fn new<X, XE, Y, YE, Z, ZE, VX, VXE, VY, VYE, VZ, VZE>(
5200 x: X,
5201 y: Y,
5202 z: Z,
5203 vx: VX,
5204 vy: VY,
5205 vz: VZ,
5206 ) -> Self
5207 where
5208 X: IntoIterator<Item = XE>,
5209 XE: Real,
5210 Y: IntoIterator<Item = YE>,
5211 YE: Real,
5212 Z: IntoIterator<Item = ZE>,
5213 ZE: Real,
5214 VX: IntoIterator<Item = VXE>,
5215 VXE: Real,
5216 VY: IntoIterator<Item = VYE>,
5217 VYE: Real,
5218 VZ: IntoIterator<Item = VZE>,
5219 VZE: Real,
5220 {
5221 Self {
5222 x: x.into_iter().map(Real::into_f64).collect(),
5223 y: y.into_iter().map(Real::into_f64).collect(),
5224 z: z.into_iter().map(Real::into_f64).collect(),
5225 vx: vx.into_iter().map(Real::into_f64).collect(),
5226 vy: vy.into_iter().map(Real::into_f64).collect(),
5227 vz: vz.into_iter().map(Real::into_f64).collect(),
5228 opts: Vec::new(),
5229 }
5230 }
5231
5232 pub fn new_triples<I, XE, YE, ZE, VI, VXE, VYE, VZE>(xyz: I, vxyz: VI) -> Self
5235 where
5236 I: IntoIterator<Item = (XE, YE, ZE)>,
5237 XE: Real,
5238 YE: Real,
5239 ZE: Real,
5240 VI: IntoIterator<Item = (VXE, VYE, VZE)>,
5241 VXE: Real,
5242 VYE: Real,
5243 VZE: Real,
5244 {
5245 let ((x, y), z): ((Vec<f64>, Vec<f64>), Vec<f64>) =
5246 xyz.into_iter()
5247 .map(|(x, y, z)| (x.into_f64(), y.into_f64(), z.into_f64()))
5248 .map(assoc)
5249 .unzip();
5250 let ((vx, vy), vz): ((Vec<f64>, Vec<f64>), Vec<f64>) =
5251 vxyz.into_iter()
5252 .map(|(x, y, z)| (x.into_f64(), y.into_f64(), z.into_f64()))
5253 .map(assoc)
5254 .unzip();
5255 Self { x, y, z, vx, vy, vz, opts: Vec::new() }
5256 }
5257
5258 pub fn new_data<I, XE, YE, ZE, VXE, VYE, VZE>(data: I) -> Self
5262 where
5263 I: IntoIterator<Item = (XE, YE, ZE, VXE, VYE, VZE)>,
5264 XE: Real,
5265 YE: Real,
5266 ZE: Real,
5267 VXE: Real,
5268 VYE: Real,
5269 VZE: Real,
5270 {
5271 let (((((x, y), z), vx), vy), vz) =
5272 data.into_iter()
5273 .map(|(a, b, c, d, e, f)| {
5274 let a = a.into_f64();
5275 let b = b.into_f64();
5276 let c = c.into_f64();
5277 let d = d.into_f64();
5278 let e = e.into_f64();
5279 let f = f.into_f64();
5280 (a, b, c, d, e, f)
5281 })
5282 .map(assoc)
5283 .unzip();
5284 Self { x, y, z, vx, vy, vz, opts: Vec::new() }
5285 }
5286}
5287
5288pub fn quiver3<X, XE, Y, YE, Z, ZE, VX, VXE, VY, VYE, VZ, VZE>(
5290 x: X,
5291 y: Y,
5292 z: Z,
5293 vx: VX,
5294 vy: VY,
5295 vz: VZ,
5296) -> Quiver3
5297where
5298 X: IntoIterator<Item = XE>,
5299 XE: Real,
5300 Y: IntoIterator<Item = YE>,
5301 YE: Real,
5302 Z: IntoIterator<Item = ZE>,
5303 ZE: Real,
5304 VX: IntoIterator<Item = VXE>,
5305 VXE: Real,
5306 VY: IntoIterator<Item = VYE>,
5307 VYE: Real,
5308 VZ: IntoIterator<Item = VZE>,
5309 VZE: Real,
5310{
5311 Quiver3::new(x, y, z, vx, vy, vz)
5312}
5313
5314pub fn quiver3_triples<I, XE, YE, ZE, VI, VXE, VYE, VZE>(xyz: I, vxyz: VI)
5317 -> Quiver3
5318where
5319 I: IntoIterator<Item = (XE, YE, ZE)>,
5320 XE: Real,
5321 YE: Real,
5322 ZE: Real,
5323 VI: IntoIterator<Item = (VXE, VYE, VZE)>,
5324 VXE: Real,
5325 VYE: Real,
5326 VZE: Real,
5327{
5328 Quiver3::new_triples(xyz, vxyz)
5329}
5330
5331pub fn quiver3_data<I, XE, YE, ZE, VXE, VYE, VZE>(data: I) -> Quiver3
5336where
5337 I: IntoIterator<Item = (XE, YE, ZE, VXE, VYE, VZE)>,
5338 XE: Real,
5339 YE: Real,
5340 ZE: Real,
5341 VXE: Real,
5342 VYE: Real,
5343 VZE: Real,
5344{
5345 Quiver3::new_data(data)
5346}
5347
5348impl Matplotlib for Quiver3 {
5349 fn is_prelude(&self) -> bool { false }
5350
5351 fn data(&self) -> Option<Value> {
5352 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
5353 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
5354 let z: Vec<Value> = self.z.iter().copied().map(Value::from).collect();
5355 let vx: Vec<Value> = self.vx.iter().copied().map(Value::from).collect();
5356 let vy: Vec<Value> = self.vy.iter().copied().map(Value::from).collect();
5357 let vz: Vec<Value> = self.vz.iter().copied().map(Value::from).collect();
5358 Some(Value::Array(vec![
5359 x.into(),
5360 y.into(),
5361 z.into(),
5362 vx.into(),
5363 vy.into(),
5364 vz.into(),
5365 ]))
5366 }
5367
5368 fn py_cmd(&self) -> String {
5369 format!(
5370 "ax.quiver(\
5371 data[0], data[1], data[2], data[3], data[4], data[5]{}{})",
5372 if self.opts.is_empty() { "" } else { ", " },
5373 self.opts.as_py(),
5374 )
5375 }
5376}
5377
5378impl MatplotlibOpts for Quiver3 {
5379 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
5380 self.opts.push((key, val).into());
5381 self
5382 }
5383}
5384
5385#[derive(Clone, Debug, PartialEq)]
5399pub struct Surface {
5400 pub x: Vec<Vec<f64>>,
5402 pub y: Vec<Vec<f64>>,
5404 pub z: Vec<Vec<f64>>,
5406 pub opts: Vec<Opt>,
5408}
5409
5410impl Surface {
5411 pub fn new<XI, XJ, XE, YI, YJ, YE, ZI, ZJ, ZE>(x: XI, y: YI, z: ZI) -> Self
5413 where
5414 XI: IntoIterator<Item = XJ>,
5415 XJ: IntoIterator<Item = XE>,
5416 XE: Real,
5417 YI: IntoIterator<Item = YJ>,
5418 YJ: IntoIterator<Item = YE>,
5419 YE: Real,
5420 ZI: IntoIterator<Item = ZJ>,
5421 ZJ: IntoIterator<Item = ZE>,
5422 ZE: Real,
5423 {
5424 let x: Vec<Vec<f64>> =
5425 x.into_iter()
5426 .map(|row| row.into_iter().map(Real::into_f64).collect())
5427 .collect();
5428 let y: Vec<Vec<f64>> =
5429 y.into_iter()
5430 .map(|row| row.into_iter().map(Real::into_f64).collect())
5431 .collect();
5432 let z: Vec<Vec<f64>> =
5433 z.into_iter()
5434 .map(|row| row.into_iter().map(Real::into_f64).collect())
5435 .collect();
5436 Self { x, y, z, opts: Vec::new() }
5437 }
5438
5439 pub fn new_flat<X, XE, Y, YE, Z, ZE>(x: X, y: Y, z: Z, rowlen: usize) -> Self
5444 where
5445 X: IntoIterator<Item = XE>,
5446 XE: Real,
5447 Y: IntoIterator<Item = YE>,
5448 YE: Real,
5449 Z: IntoIterator<Item = ZE>,
5450 ZE: Real,
5451 {
5452 if rowlen == 0 { panic!("row length cannot be zero"); }
5453 let x: Vec<Vec<f64>> =
5454 Chunks::new(x.into_iter().map(Real::into_f64), rowlen)
5455 .collect();
5456 let y: Vec<Vec<f64>> =
5457 Chunks::new(y.into_iter().map(Real::into_f64), rowlen)
5458 .collect();
5459 let z: Vec<Vec<f64>> =
5460 Chunks::new(z.into_iter().map(Real::into_f64), rowlen)
5461 .collect();
5462 Self { x, y, z, opts: Vec::new() }
5463 }
5464
5465 pub fn new_data<I, XE, YE, ZE>(data: I, rowlen: usize) -> Self
5470 where
5471 I: IntoIterator<Item = (XE, YE, ZE)>,
5472 XE: Real,
5473 YE: Real,
5474 ZE: Real,
5475 {
5476 if rowlen == 0 { panic!("row length cannot be zero"); }
5477 let mut x: Vec<Vec<f64>> = Vec::new();
5478 let mut y: Vec<Vec<f64>> = Vec::new();
5479 let mut z: Vec<Vec<f64>> = Vec::new();
5480 Chunks::new(data.into_iter(), rowlen)
5481 .for_each(|points| {
5482 let mut xi: Vec<f64> = Vec::with_capacity(rowlen);
5483 let mut yi: Vec<f64> = Vec::with_capacity(rowlen);
5484 let mut zi: Vec<f64> = Vec::with_capacity(rowlen);
5485 points.into_iter()
5486 .for_each(|(xij, yij, zij)| {
5487 xi.push(xij.into_f64());
5488 yi.push(yij.into_f64());
5489 zi.push(zij.into_f64());
5490 });
5491 x.push(xi);
5492 y.push(yi);
5493 z.push(zi);
5494 });
5495 Self { x, y, z, opts: Vec::new() }
5496 }
5497}
5498
5499pub fn surface<XI, XJ, XE, YI, YJ, YE, ZI, ZJ, ZE>(x: XI, y: YI, z: ZI)
5501 -> Surface
5502where
5503 XI: IntoIterator<Item = XJ>,
5504 XJ: IntoIterator<Item = XE>,
5505 XE: Real,
5506 YI: IntoIterator<Item = YJ>,
5507 YJ: IntoIterator<Item = YE>,
5508 YE: Real,
5509 ZI: IntoIterator<Item = ZJ>,
5510 ZJ: IntoIterator<Item = ZE>,
5511 ZE: Real,
5512{
5513 Surface::new(x, y, z)
5514}
5515
5516pub fn surface_flat<X, XE, Y, YE, Z, ZE>(x: X, y: Y, z: Z, rowlen: usize) -> Surface
5521where
5522 X: IntoIterator<Item = XE>,
5523 XE: Real,
5524 Y: IntoIterator<Item = YE>,
5525 YE: Real,
5526 Z: IntoIterator<Item = ZE>,
5527 ZE: Real,
5528{
5529 Surface::new_flat(x, y, z, rowlen)
5530}
5531
5532pub fn surface_data<I, XE, YE, ZE>(data: I, rowlen: usize) -> Surface
5537where
5538 I: IntoIterator<Item = (XE, YE, ZE)>,
5539 XE: Real,
5540 YE: Real,
5541 ZE: Real,
5542{
5543 Surface::new_data(data, rowlen)
5544}
5545
5546impl Matplotlib for Surface {
5547 fn is_prelude(&self) -> bool { false }
5548
5549 fn data(&self) -> Option<Value> {
5550 let x: Vec<Value> =
5551 self.x.iter()
5552 .map(|row| {
5553 let row: Vec<Value> =
5554 row.iter().copied().map(Value::from).collect();
5555 Value::Array(row)
5556 })
5557 .collect();
5558 let y: Vec<Value> =
5559 self.y.iter()
5560 .map(|row| {
5561 let row: Vec<Value> =
5562 row.iter().copied().map(Value::from).collect();
5563 Value::Array(row)
5564 })
5565 .collect();
5566 let z: Vec<Value> =
5567 self.z.iter()
5568 .map(|row| {
5569 let row: Vec<Value> =
5570 row.iter().copied().map(Value::from).collect();
5571 Value::Array(row)
5572 })
5573 .collect();
5574 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
5575 }
5576
5577 fn py_cmd(&self) -> String {
5578 format!("\
5579 ax.plot_surface(\
5580 np.array(data[0]), \
5581 np.array(data[1]), \
5582 np.array(data[2])\
5583 {}{})",
5584 if self.opts.is_empty() { "" } else { ", " },
5585 self.opts.as_py(),
5586 )
5587 }
5588}
5589
5590impl MatplotlibOpts for Surface {
5591 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
5592 self.opts.push((key, val).into());
5593 self
5594 }
5595}
5596
5597#[derive(Clone, Debug, PartialEq)]
5607pub struct Trisurf {
5608 pub x: Vec<f64>,
5610 pub y: Vec<f64>,
5612 pub z: Vec<f64>,
5614 pub opts: Vec<Opt>,
5616}
5617
5618impl Trisurf {
5619 pub fn new<X, XE, Y, YE, Z, ZE>(x: X, y: Y, z: Z) -> Self
5621 where
5622 X: IntoIterator<Item = XE>,
5623 XE: Real,
5624 Y: IntoIterator<Item = YE>,
5625 YE: Real,
5626 Z: IntoIterator<Item = ZE>,
5627 ZE: Real,
5628 {
5629 Self {
5630 x: x.into_iter().map(Real::into_f64).collect(),
5631 y: y.into_iter().map(Real::into_f64).collect(),
5632 z: z.into_iter().map(Real::into_f64).collect(),
5633 opts: Vec::new(),
5634 }
5635 }
5636
5637 pub fn new_data<I, XE, YE, ZE>(data: I) -> Self
5639 where
5640 I: IntoIterator<Item = (XE, YE, ZE)>,
5641 XE: Real,
5642 YE: Real,
5643 ZE: Real,
5644 {
5645 let ((x, y), z) =
5646 data.into_iter()
5647 .map(|(a, b, c)| (a.into_f64(), b.into_f64(), c.into_f64()))
5648 .map(assoc)
5649 .unzip();
5650 Self { x, y, z, opts: Vec::new() }
5651 }
5652}
5653
5654pub fn trisurf<X, XE, Y, YE, Z, ZE>(x: X, y: Y, z: Z) -> Trisurf
5656where
5657 X: IntoIterator<Item = XE>,
5658 XE: Real,
5659 Y: IntoIterator<Item = YE>,
5660 YE: Real,
5661 Z: IntoIterator<Item = ZE>,
5662 ZE: Real,
5663{
5664 Trisurf::new(x, y, z)
5665}
5666
5667pub fn trisurf_data<I, XE, YE, ZE>(data: I) -> Trisurf
5669where
5670 I: IntoIterator<Item = (XE, YE, ZE)>,
5671 XE: Real,
5672 YE: Real,
5673 ZE: Real,
5674{
5675 Trisurf::new_data(data)
5676}
5677
5678impl Matplotlib for Trisurf {
5679 fn is_prelude(&self) -> bool { false }
5680
5681 fn data(&self) -> Option<Value> {
5682 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
5683 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
5684 let z: Vec<Value> = self.z.iter().copied().map(Value::from).collect();
5685 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
5686 }
5687
5688 fn py_cmd(&self) -> String {
5689 format!("ax.plot_trisurf(data[0], data[1], data[2]{}{})",
5690 if self.opts.is_empty() { "" } else { ", " },
5691 self.opts.as_py(),
5692 )
5693 }
5694}
5695
5696impl MatplotlibOpts for Trisurf {
5697 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
5698 self.opts.push((key, val).into());
5699 self
5700 }
5701}
5702
5703#[derive(Clone, Debug, PartialEq)]
5715pub struct ViewInit {
5716 pub azim: f64,
5718 pub elev: f64,
5720 pub opts: Vec<Opt>,
5722}
5723
5724impl ViewInit {
5725 pub fn new(azim: f64, elev: f64) -> Self {
5727 Self { azim, elev, opts: Vec::new() }
5728 }
5729}
5730
5731pub fn view_init(azim: f64, elev: f64) -> ViewInit { ViewInit::new(azim, elev) }
5733
5734impl Matplotlib for ViewInit {
5735 fn is_prelude(&self) -> bool { false }
5736
5737 fn data(&self) -> Option<Value> { None }
5738
5739 fn py_cmd(&self) -> String {
5740 format!("ax.view_init(azim={}, elev={}{}{})",
5741 self.azim.as_py(),
5742 self.elev.as_py(),
5743 if self.opts.is_empty() { "" } else { ", " },
5744 self.opts.as_py(),
5745 )
5746 }
5747}
5748
5749impl MatplotlibOpts for ViewInit {
5750 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
5751 self.opts.push((key, val).into());
5752 self
5753 }
5754}
5755
5756pub trait Associator<P> {
5792 fn assoc(self) -> P;
5794}
5795
5796impl<A, B, C> Associator<((A, B), C)> for (A, B, C) {
5800 fn assoc(self) -> ((A, B), C) { ((self.0, self.1), self.2) }
5801}
5802
5803impl<A, B, C> Associator<(A, B, C)> for ((A, B), C) {
5804 fn assoc(self) -> (A, B, C) { (self.0.0, self.0.1, self.1) }
5805}
5806
5807impl<A, B, C> Associator<(A, (B, C))> for (A, B, C) {
5808 fn assoc(self) -> (A, (B, C)) { (self.0, (self.1, self.2)) }
5809}
5810
5811impl<A, B, C> Associator<(A, B, C)> for (A, (B, C)) {
5812 fn assoc(self) -> (A, B, C) { (self.0, self.1.0, self.1.1) }
5813}
5814
5815macro_rules! impl_biassoc {
5818 (
5819 <$( $gen:ident ),+>,
5820 $pair:ty,
5821 ($( $l:ident ),+),
5822 $r:ident $(,)?
5823 ) => {
5824 impl<$( $gen ),+> Associator<$pair> for ($( $gen ),+) {
5825 fn assoc(self) -> $pair {
5826 let ($( $l ),+, $r) = self;
5827 (($( $l ),+).assoc(), $r)
5828 }
5829 }
5830
5831 impl<$( $gen ),+> Associator<($( $gen ),+)> for $pair {
5832 fn assoc(self) -> ($( $gen ),+) {
5833 let ($( $l ),+) = self.0.assoc();
5834 ($( $l ),+, self.1)
5835 }
5836 }
5837 };
5838 (
5839 <$( $gen:ident ),+>,
5840 $pair:ty,
5841 $l:ident,
5842 ($( $r:ident ),+) $(,)?
5843 ) => {
5844 impl<$( $gen ),+> Associator<$pair> for ($( $gen ),+) {
5845 fn assoc(self) -> $pair {
5846 let ($l, $( $r ),+) = self;
5847 ($l, ($( $r ),+).assoc())
5848 }
5849 }
5850
5851 impl<$( $gen ),+> Associator<($( $gen ),+)> for $pair {
5852 fn assoc(self) -> ($( $gen ),+) {
5853 let ($( $r ),+) = self.1.assoc();
5854 (self.0, $( $r ),+)
5855 }
5856 }
5857 };
5858}
5859
5860impl_biassoc!(<A, B, C, D>, (((A, B), C), D), (a, b, c), d);
5861impl_biassoc!(<A, B, C, D>, ((A, (B, C)), D), (a, b, c), d);
5862impl_biassoc!(<A, B, C, D>, (A, ((B, C), D)), a, (b, c, d));
5863impl_biassoc!(<A, B, C, D>, (A, (B, (C, D))), a, (b, c, d));
5864impl_biassoc!(<A, B, C, D, E>, ((((A, B), C), D), E), (a, b, c, d), e);
5865impl_biassoc!(<A, B, C, D, E>, (((A, (B, C)), D), E), (a, b, c, d), e);
5866impl_biassoc!(<A, B, C, D, E>, ((A, ((B, C), D)), E), (a, b, c, d), e);
5867impl_biassoc!(<A, B, C, D, E>, ((A, (B, (C, D))), E), (a, b, c, d), e);
5868impl_biassoc!(<A, B, C, D, E>, (A, (((B, C), D), E)), a, (b, c, d, e));
5869impl_biassoc!(<A, B, C, D, E>, (A, ((B, (C, D)), E)), a, (b, c, d, e));
5870impl_biassoc!(<A, B, C, D, E>, (A, (B, ((C, D), E))), a, (b, c, d, e));
5871impl_biassoc!(<A, B, C, D, E>, (A, (B, (C, (D, E)))), a, (b, c, d, e));
5872impl_biassoc!(<A, B, C, D, E, F>, (((((A, B), C), D), E), F), (a, b, c, d, e), f);
5873impl_biassoc!(<A, B, C, D, E, F>, ((((A, (B, C)), D), E), F), (a, b, c, d, e), f);
5874impl_biassoc!(<A, B, C, D, E, F>, (((A, ((B, C), D)), E), F), (a, b, c, d, e), f);
5875impl_biassoc!(<A, B, C, D, E, F>, (((A, (B, (C, D))), E), F), (a, b, c, d, e), f);
5876impl_biassoc!(<A, B, C, D, E, F>, ((A, (((B, C), D), E)), F), (a, b, c, d, e), f);
5877impl_biassoc!(<A, B, C, D, E, F>, ((A, ((B, (C, D)), E)), F), (a, b, c, d, e), f);
5878impl_biassoc!(<A, B, C, D, E, F>, ((A, (B, ((C, D), E))), F), (a, b, c, d, e), f);
5879impl_biassoc!(<A, B, C, D, E, F>, ((A, (B, (C, (D, E)))), F), (a, b, c, d, e), f);
5880impl_biassoc!(<A, B, C, D, E, F>, (A, ((((B, C), D), E), F)), a, (b, c, d, e, f));
5881impl_biassoc!(<A, B, C, D, E, F>, (A, (((B, (C, D)), E), F)), a, (b, c, d, e, f));
5882impl_biassoc!(<A, B, C, D, E, F>, (A, ((B, ((C, D), E)), F)), a, (b, c, d, e, f));
5883impl_biassoc!(<A, B, C, D, E, F>, (A, ((B, (C, (D, E))), F)), a, (b, c, d, e, f));
5884impl_biassoc!(<A, B, C, D, E, F>, (A, (B, (((C, D), E), F))), a, (b, c, d, e, f));
5885impl_biassoc!(<A, B, C, D, E, F>, (A, (B, ((C, (D, E)), F))), a, (b, c, d, e, f));
5886impl_biassoc!(<A, B, C, D, E, F>, (A, (B, (C, ((D, E), F)))), a, (b, c, d, e, f));
5887impl_biassoc!(<A, B, C, D, E, F>, (A, (B, (C, (D, (E, F))))), a, (b, c, d, e, f));
5888
5889pub fn assoc<A, B>(a: A) -> B
5892where A: Associator<B>
5893{
5894 a.assoc()
5895}
5896
5897pub fn assoc_iter<I, J, A, B>(iter: I) -> std::iter::Map<J, fn(A) -> B>
5899where
5900 I: IntoIterator<IntoIter = J, Item = A>,
5901 J: Iterator<Item = A>,
5902 A: Associator<B>,
5903{
5904 iter.into_iter().map(assoc)
5905}
5906
5907#[cfg(test)]
5908mod tests {
5909 use crate::{ Mpl, Run, MatplotlibOpts, opt, GSPos };
5910 use super::*;
5911
5912 fn runner() -> Run { Run::Debug }
5913
5914 #[test]
5915 fn test_prelude_init() {
5916 Mpl::default()
5917 | runner()
5918 }
5919
5920 #[test]
5921 fn test_axhline() {
5922 Mpl::default()
5923 & axhline(10.0).o("linestyle", "-")
5924 | runner()
5925 }
5926
5927 #[test]
5928 fn test_axline() {
5929 Mpl::default()
5930 & axline((0.0, 0.0), (10.0, 10.0)).o("linestyle", "-")
5931 | runner()
5932 }
5933
5934 #[test]
5935 fn test_axlinem() {
5936 Mpl::default()
5937 & axlinem((0.0, 0.0), 1.0).o("linestyle", "-")
5938 | runner()
5939 }
5940
5941 #[test]
5942 fn test_axtext() {
5943 Mpl::default()
5944 & axtext(0.5, 0.5, "hello world").o("ha", "left").o("va", "bottom")
5945 | runner()
5946 }
5947
5948 #[test]
5949 fn test_axvline() {
5950 Mpl::default()
5951 & axvline(10.0).o("linestyle", "-")
5952 | runner()
5953 }
5954
5955 #[test]
5956 fn test_bar() {
5957 Mpl::default()
5958 & bar([0.0, 1.0], [0.5, 0.5]).o("color", "C0")
5959 | runner()
5960 }
5961
5962 #[test]
5963 fn test_bar_pairs() {
5964 Mpl::default()
5965 & bar_pairs([(0.0, 0.5), (1.0, 0.5)]).o("color", "C0")
5966 | runner()
5967 }
5968
5969 #[test]
5970 fn test_bar_eq() {
5971 assert_eq!(
5972 bar([0.0, 1.0], [0.5, 0.5]).o("color", "C0"),
5973 bar_pairs([(0.0, 0.5), (1.0, 0.5)]).o("color", "C0"),
5974 )
5975 }
5976
5977 #[test]
5978 fn test_barh() {
5979 Mpl::default()
5980 & barh([0.0, 1.0], [0.5, 0.5]).o("color", "C0")
5981 | runner()
5982 }
5983
5984 #[test]
5985 fn test_barh_pairs() {
5986 Mpl::default()
5987 & barh_pairs([(0.0, 0.5), (1.0, 0.5)]).o("color", "C0")
5988 | runner()
5989 }
5990
5991 #[test]
5992 fn test_barh_eq() {
5993 assert_eq!(
5994 barh([0.0, 1.0], [0.5, 0.5]).o("color", "C0"),
5995 barh_pairs([(0.0, 0.5), (1.0, 0.5)]).o("color", "C0"),
5996 )
5997 }
5998
5999 #[test]
6000 fn test_boxplot() {
6001 Mpl::default()
6002 & boxplot([[0.0, 1.0, 2.0], [2.0, 3.0, 4.0]]).o("notch", true)
6003 | runner()
6004 }
6005
6006 #[test]
6007 fn test_boxplot_flat() {
6008 Mpl::default()
6009 & boxplot_flat([0.0, 1.0, 2.0, 2.0, 3.0, 4.0], 3).o("notch", true)
6010 | runner()
6011 }
6012
6013 #[test]
6014 fn test_boxplot_eq() {
6015 assert_eq!(
6016 boxplot([[0.0, 1.0, 2.0], [2.0, 3.0, 4.0]]).o("notch", true),
6017 boxplot_flat([0.0, 1.0, 2.0, 2.0, 3.0, 4.0], 3).o("notch", true),
6018 )
6019 }
6020
6021 #[test]
6022 fn test_clabel() {
6023 Mpl::default()
6024 & imshow([[0.0, 1.0], [2.0, 3.0]])
6025 & colorbar()
6026 & clabel("hello world").o("fontsize", "medium")
6027 | runner()
6028 }
6029
6030 #[test]
6031 fn test_clim() {
6032 Mpl::default()
6033 & imshow([[0.0, 1.0], [2.0, 3.0]])
6034 & colorbar()
6035 & clim(Some(0.0), Some(1.0))
6036 | runner()
6037 }
6038
6039 #[test]
6040 fn test_colorbar() {
6041 Mpl::default()
6042 & imshow([[0.0, 1.0], [2.0, 3.0]])
6043 & colorbar().o("location", "top")
6044 | runner()
6045 }
6046
6047 #[test]
6048 fn test_contour() {
6049 Mpl::default()
6050 & contour([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
6051 .o("cmap", "bone")
6052 & colorbar()
6053 | runner()
6054 }
6055
6056 #[test]
6057 fn test_contour_flat() {
6058 Mpl::default()
6059 & contour_flat([0.0, 1.0], [0.0, 1.0], [0.0, 1.0, 2.0, 3.0])
6060 .o("cmap", "bone")
6061 & colorbar()
6062 | runner()
6063 }
6064
6065 #[test]
6066 fn test_contour_eq() {
6067 assert_eq!(
6068 contour([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
6069 .o("cmap", "bone"),
6070 contour_flat([0.0, 1.0], [0.0, 1.0], [0.0, 1.0, 2.0, 3.0])
6071 .o("cmap", "bone"),
6072 )
6073 }
6074
6075 #[test]
6076 fn test_contour_labels() {
6077 Mpl::default()
6078 & contour([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
6079 .o("cmap", "bone")
6080 .o("levels", [0.5, 1.0, 1.5, 2.0, 2.5])
6081 & colorbar()
6082 & contour_labels()
6083 .on_levels([1.0, 2.0])
6084 .with_fmt("x", "f\"{x:.6f}\"")
6085 .o("fontsize", "medium")
6086 | runner()
6087 }
6088
6089 #[test]
6090 fn test_contourf() {
6091 Mpl::default()
6092 & contour([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
6093 .o("cmap", "bone")
6094 & colorbar()
6095 | runner()
6096 }
6097
6098 #[test]
6099 fn test_contourf_flat() {
6100 Mpl::default()
6101 & contour_flat([0.0, 1.0], [0.0, 1.0], [0.0, 1.0, 2.0, 3.0])
6102 .o("cmap", "bone")
6103 & colorbar()
6104 | runner()
6105 }
6106
6107 #[test]
6108 fn test_contourf_eq() {
6109 assert_eq!(
6110 contourf([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
6111 .o("cmap", "bone"),
6112 contourf_flat([0.0, 1.0], [0.0, 1.0], [0.0, 1.0, 2.0, 3.0])
6113 .o("cmap", "bone"),
6114 )
6115 }
6116
6117 #[test]
6118 fn test_cticklabels() {
6119 Mpl::default()
6120 & imshow([[0.0, 1.0], [2.0, 3.0]])
6121 & colorbar()
6122 & cticklabels([0.0, 1.0], ["zero", "one"]).o("minor", true)
6123 | runner()
6124 }
6125
6126 #[test]
6127 fn test_cticklabels_data() {
6128 Mpl::default()
6129 & imshow([[0.0, 1.0], [2.0, 3.0]])
6130 & colorbar()
6131 & cticklabels_data([(0.0, "zero"), (1.0, "one")]).o("minor", true)
6132 | runner()
6133 }
6134
6135 #[test]
6136 fn test_cticklabels_eq() {
6137 assert_eq!(
6138 cticklabels([0.0, 1.0], ["zero", "one"]).o("minor", true),
6139 cticklabels_data([(0.0, "zero"), (1.0, "one")]).o("minor", true),
6140 )
6141 }
6142
6143 #[test]
6144 fn test_cticks() {
6145 Mpl::default()
6146 & imshow([[0.0, 1.0], [2.0, 3.0]])
6147 & colorbar()
6148 & cticks([0.0, 1.0])
6149 .o("labels", PyValue::list(["zero", "one"]))
6150 | runner()
6151 }
6152
6153 #[test]
6154 fn test_errorbar() {
6155 Mpl::default()
6156 & errorbar([0.0, 1.0], [0.0, 1.0], [0.5, 1.0]).o("color", "C0")
6157 | runner()
6158 }
6159
6160 #[test]
6161 fn test_errorbar_data() {
6162 Mpl::default()
6163 & errorbar_data([(0.0, 0.0, 0.5), (1.0, 1.0, 1.0)]).o("color", "C0")
6164 | runner()
6165 }
6166
6167 #[test]
6168 fn test_errorbar_eq() {
6169 assert_eq!(
6170 errorbar([0.0, 1.0], [0.0, 1.0], [0.5, 1.0]).o("color", "C0"),
6171 errorbar_data([(0.0, 0.0, 0.5), (1.0, 1.0, 1.0)]).o("color", "C0"),
6172 )
6173 }
6174
6175 #[test]
6176 fn test_errorbar2() {
6177 Mpl::default()
6178 & errorbar2([0.0, 1.0], [0.0, 1.0], [1.0, 0.5], [0.5, 1.0])
6179 .o("color", "C0")
6180 | runner()
6181 }
6182
6183 #[test]
6184 fn test_errorbar2_data() {
6185 Mpl::default()
6186 & errorbar2_data([(0.0, 0.0, 1.0, 0.5), (1.0, 1.0, 0.5, 1.0)])
6187 .o("color", "C0")
6188 | runner()
6189 }
6190
6191 #[test]
6192 fn test_errorbar2_eq() {
6193 assert_eq!(
6194 errorbar2([0.0, 1.0], [0.0, 1.0], [1.0, 0.5], [0.5, 1.0])
6195 .o("color", "C0"),
6196 errorbar2_data([(0.0, 0.0, 1.0, 0.5), (1.0, 1.0, 0.5, 1.0)])
6197 .o("color", "C0"),
6198 )
6199 }
6200
6201 #[test]
6202 fn test_figtext() {
6203 Mpl::default()
6204 & figtext(0.5, 0.5, "hello world").o("ha", "left").o("va", "bottom")
6205 | runner()
6206 }
6207
6208 #[test]
6209 fn test_fill_between() {
6210 Mpl::default()
6211 & fill_between([0.0, 1.0], [-0.5, 0.0], [0.5, 2.0]).o("color", "C0")
6212 | runner()
6213 }
6214
6215 #[test]
6216 fn test_fill_between_data() {
6217 Mpl::default()
6218 & fill_between_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)])
6219 .o("color", "C0")
6220 | runner()
6221 }
6222
6223 #[test]
6224 fn test_fill_between_eq() {
6225 assert_eq!(
6226 fill_between([0.0, 1.0], [-0.5, 0.0], [0.5, 2.0]).o("color", "C0"),
6227 fill_between_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)])
6228 .o("color", "C0"),
6229 )
6230 }
6231
6232 #[test]
6233 fn test_fillbetween_from_errorbar() {
6234 let ebar =
6235 errorbar_data([(0.0, 0.0, 0.5), (1.0, 1.0, 1.0)]);
6236 let ebar2 =
6237 errorbar2_data([(0.0, 0.25, 0.75, 0.25), (1.0, 1.0, 1.0, 1.0)]);
6238 let fbetw =
6239 fill_between_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)]);
6240 assert_eq!(FillBetween::from(ebar), fbetw);
6241 assert_eq!(FillBetween::from(ebar2), fbetw);
6242 }
6243
6244 #[test]
6245 fn test_errorbar_from_fillbetween() {
6246 let fbetw = fill_between_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)]);
6247 let ebar = errorbar_data([(0.0, 0.0, 0.5), (1.0, 1.0, 1.0)]);
6248 assert_eq!(Errorbar::from(fbetw), ebar);
6249 }
6250
6251 #[test]
6252 fn test_fill_betweenx() {
6253 Mpl::default()
6254 & fill_betweenx([0.0, 1.0], [-0.5, 0.0], [0.5, 2.0])
6255 .o("color", "C0")
6256 | runner()
6257 }
6258
6259 #[test]
6260 fn test_fill_betweenx_data() {
6261 Mpl::default()
6262 & fill_betweenx_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)])
6263 .o("color", "C0")
6264 | runner()
6265 }
6266
6267 #[test]
6268 fn test_fill_betweenx_eq() {
6269 assert_eq!(
6270 fill_betweenx([0.0, 1.0], [-0.5, 0.0], [0.5, 2.0]).o("color", "C0"),
6271 fill_betweenx_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)])
6272 .o("color", "C0"),
6273 )
6274 }
6275
6276 #[test]
6277 fn test_grid() {
6278 Mpl::default()
6279 & grid(true).o("which", "both")
6280 | runner()
6281 }
6282
6283 #[test]
6284 fn test_hist() {
6285 Mpl::default()
6286 & hist([0.0, 1.0, 2.0])
6287 .o("bins", PyValue::list([-0.5, 0.5, 1.5, 2.5]))
6288 | runner()
6289 }
6290
6291 #[test]
6292 fn test_hist2d() {
6293 Mpl::default()
6294 & hist2d([0.0, 1.0, 2.0], [0.0, 2.0, 4.0]).o("cmap", "bone")
6295 | runner()
6296 }
6297
6298 #[test]
6299 fn test_hist2d_pairs() {
6300 Mpl::default()
6301 & hist2d_pairs([(0.0, 0.0), (1.0, 2.0), (2.0, 4.0)])
6302 .o("cmap", "bone")
6303 | runner()
6304 }
6305
6306 #[test]
6307 fn test_hist2d_eq() {
6308 assert_eq!(
6309 hist2d([0.0, 1.0, 2.0], [0.0, 2.0, 4.0]).o("cmap", "bone"),
6310 hist2d_pairs([(0.0, 0.0), (1.0, 2.0), (2.0, 4.0)]).o("cmap", "bone"),
6311 )
6312 }
6313
6314 #[test]
6315 fn test_violinplot() {
6316 Mpl::default()
6317 & violinplot([[0.0, 1.0], [2.0, 3.0]]).o("vert", false)
6318 | runner()
6319 }
6320
6321 #[test]
6322 fn test_violinplot_flat() {
6323 Mpl::default()
6324 & violinplot_flat([0.0, 1.0, 2.0, 3.0], 2).o("vert", false)
6325 | runner()
6326 }
6327
6328 #[test]
6329 fn test_violinplot_eq() {
6330 assert_eq!(
6331 violinplot([[0.0, 1.0], [2.0, 3.0]]).o("vert", false),
6332 violinplot_flat([0.0, 1.0, 2.0, 3.0], 2).o("vert", false),
6333 )
6334 }
6335
6336 #[test]
6337 fn test_imshow() {
6338 Mpl::default()
6339 & imshow([[0.0, 1.0], [2.0, 3.0]]).o("cmap", "bone")
6340 | runner()
6341 }
6342
6343 #[test]
6344 fn test_colorplot() {
6345 Mpl::default()
6346 & colorplot(
6347 [0.0, 1.0, 1.5],
6348 [2.0, 3.0, 3.5],
6349 [[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]
6350 )
6351 .o("cmap", "bone")
6352 | runner()
6353 }
6354
6355 #[test]
6356 fn test_colorplot_flat() {
6357 Mpl::default()
6358 & colorplot_flat(
6359 [0.0, 1.0, 1.5],
6360 [2.0, 3.0, 3.5],
6361 [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
6362 )
6363 .o("cmap", "bone")
6364 | runner()
6365 }
6366
6367 #[test]
6368 fn test_colorplot_eq() {
6369 assert_eq!(
6370 colorplot(
6371 [0.0, 1.0, 1.5],
6372 [2.0, 3.0, 3.5],
6373 [[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]
6374 ).o("cmap", "bone"),
6375 colorplot_flat(
6376 [0.0, 1.0, 1.5],
6377 [2.0, 3.0, 3.5],
6378 [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
6379 ).o("cmap", "bone"),
6380 )
6381 }
6382
6383 #[test]
6384 fn test_imshow_flat() {
6385 Mpl::default()
6386 & imshow_flat([0.0, 1.0, 2.0, 3.0], 2).o("cmap", "bone")
6387 | runner()
6388 }
6389
6390 #[test]
6391 fn test_imshow_eq() {
6392 assert_eq!(
6393 imshow([[0.0, 1.0], [2.0, 3.0]]).o("cmap", "bone"),
6394 imshow_flat([0.0, 1.0, 2.0, 3.0], 2).o("cmap", "bone"),
6395 )
6396 }
6397
6398 #[test]
6399 fn test_inset_axes() {
6400 Mpl::default()
6401 & inset_axes(0.5, 0.5, 0.25, 0.25).o("polar", true)
6402 | runner()
6403 }
6404
6405 #[test]
6406 fn test_inset_axes_pairs() {
6407 Mpl::default()
6408 & inset_axes_pairs((0.5, 0.5), (0.25, 0.25)).o("polar", true)
6409 | runner()
6410 }
6411
6412 #[test]
6413 fn test_label() {
6414 Mpl::default()
6415 & label(Axis::X, "xlabel").o("fontsize", "large")
6416 & label(Axis::Y, "ylabel").o("fontsize", "large")
6417 | runner()
6418 }
6419
6420 #[test]
6421 fn test_xlabel() {
6422 Mpl::default()
6423 & xlabel("xlabel").o("fontsize", "large")
6424 | runner()
6425 }
6426
6427 #[test]
6428 fn test_ylabel() {
6429 Mpl::default()
6430 & ylabel("ylabel").o("fontsize", "large")
6431 | runner()
6432 }
6433
6434 #[test]
6435 fn test_label_eq() {
6436 assert_eq!(label(Axis::X, "xlabel"), xlabel("xlabel"));
6437 assert_eq!(label(Axis::Y, "ylabel"), ylabel("ylabel"));
6438 }
6439
6440 #[test]
6441 fn test_legend() {
6442 Mpl::default()
6443 & plot([0.0], [0.0]).o("label", "hello world")
6444 & legend().o("loc", "lower left")
6445 | runner()
6446 }
6447
6448 #[test]
6449 fn test_lim() {
6450 Mpl::default()
6451 & lim(Axis::X, Some(-10.0), Some(10.0))
6452 & lim(Axis::Y, Some(-10.0), Some(10.0))
6453 | runner()
6454 }
6455
6456 #[test]
6457 fn test_xlim() {
6458 Mpl::default()
6459 & xlim(Some(-10.0), Some(10.0))
6460 | runner()
6461 }
6462
6463 #[test]
6464 fn test_ylim() {
6465 Mpl::default()
6466 & ylim(Some(-10.0), Some(10.0))
6467 | runner()
6468 }
6469
6470 #[test]
6471 fn test_lim_eq() {
6472 assert_eq!(
6473 lim(Axis::X, Some(-10.0), Some(15.0)),
6474 xlim(Some(-10.0), Some(15.0)),
6475 );
6476 assert_eq!(
6477 lim(Axis::Y, Some(-10.0), Some(15.0)),
6478 ylim(Some(-10.0), Some(15.0)),
6479 );
6480 assert_eq!(
6481 lim(Axis::Z, Some(-10.0), Some(15.0)),
6482 zlim(Some(-10.0), Some(15.0)),
6483 )
6484 }
6485
6486 #[test]
6487 fn test_pie() {
6488 Mpl::default()
6489 & pie([1.0, 2.0]).o("radius", 2)
6490 | runner()
6491 }
6492
6493 #[test]
6494 fn test_plot() {
6495 Mpl::default()
6496 & plot([0.0, 1.0], [0.0, 1.0]).o("color", "C0")
6497 | runner()
6498 }
6499
6500 #[test]
6501 fn test_plot_empty() {
6502 Mpl::default()
6503 & plot::<_, f64, _, f64>([], []).o("color", "C0")
6504 | runner()
6505 }
6506
6507 #[test]
6508 fn test_plot_borrowed() {
6509 Mpl::default()
6510 & plot(&[0.0, 1.0], &[0.0, 1.0]).o("color", "C0")
6511 | runner()
6512 }
6513
6514 #[test]
6515 fn test_plot_pairs() {
6516 Mpl::default()
6517 & plot_pairs([(0.0, 0.0), (1.0, 1.0)]).o("color", "C0")
6518 | runner()
6519 }
6520
6521 #[test]
6522 fn test_plot_eq() {
6523 assert_eq!(
6524 plot([0.0, 1.0], [0.0, 1.0]).o("color", "C0"),
6525 plot_pairs([(0.0, 0.0), (1.0, 1.0)]).o("color", "C0"),
6526 )
6527 }
6528
6529 #[test]
6530 fn test_quiver() {
6531 Mpl::default()
6532 & quiver([0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0])
6533 .o("pivot", "middle")
6534 | runner()
6535 }
6536
6537 #[test]
6538 fn test_quiver_data() {
6539 Mpl::default()
6540 & quiver_data([(0.0, 0.0, 0.0, 0.0), (1.0, 1.0, 1.0, 1.0)])
6541 .o("pivot", "middle")
6542 | runner()
6543 }
6544
6545 #[test]
6546 fn test_quiver_pairs() {
6547 Mpl::default()
6548 & quiver_pairs([(0.0, 0.0), (1.0, 1.0)], [(0.0, 0.0), (1.0, 1.0)])
6549 .o("pivot", "middle")
6550 | runner()
6551 }
6552
6553 #[test]
6554 fn test_quiver_eq() {
6555 let norm =
6556 quiver([0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0])
6557 .o("pivot", "middle");
6558 let data =
6559 quiver_data([(0.0, 0.0, 0.0, 0.0), (1.0, 1.0, 1.0, 1.0)])
6560 .o("pivot", "middle");
6561 let pairs =
6562 quiver_pairs([(0.0, 0.0), (1.0, 1.0)], [(0.0, 0.0), (1.0, 1.0)])
6563 .o("pivot", "middle");
6564 assert_eq!(norm, data);
6565 assert_eq!(norm, pairs);
6566 }
6567
6568 #[test]
6569 fn test_rcparam() {
6570 Mpl::default()
6571 & rcparam("figure.figsize", PyValue::list([2.5, 3.5]))
6572 | runner()
6573 }
6574
6575 #[test]
6576 fn test_scale() {
6577 Mpl::default()
6578 & scale(Axis::X, AxisScale::Log)
6579 & scale(Axis::Y, AxisScale::Logit)
6580 | runner()
6581 }
6582
6583 #[test]
6584 fn test_xscale() {
6585 Mpl::default()
6586 & xscale(AxisScale::Log)
6587 | runner()
6588 }
6589
6590 #[test]
6591 fn test_yscale() {
6592 Mpl::default()
6593 & yscale(AxisScale::Logit)
6594 | runner()
6595 }
6596
6597 #[test]
6598 fn test_scale_eq() {
6599 assert_eq!(scale(Axis::X, AxisScale::Log), xscale(AxisScale::Log));
6600 assert_eq!(scale(Axis::Y, AxisScale::Logit), yscale(AxisScale::Logit));
6601 assert_eq!(scale(Axis::Z, AxisScale::SymLog), zscale(AxisScale::SymLog));
6602 }
6603
6604 #[test]
6605 fn test_scatter() {
6606 Mpl::default()
6607 & scatter([0.0, 1.0], [0.0, 1.0]).o("marker", "D")
6608 | runner()
6609 }
6610
6611 #[test]
6612 fn test_scatter_pairs() {
6613 Mpl::default()
6614 & scatter_pairs([(0.0, 0.0), (1.0, 1.0)]).o("marker", "D")
6615 | runner()
6616 }
6617
6618 #[test]
6619 fn test_scatter_eq() {
6620 assert_eq!(
6621 scatter([0.0, 1.0], [0.0, 1.0]).o("marker", "D"),
6622 scatter_pairs([(0.0, 0.0), (1.0, 1.0)]).o("marker", "D"),
6623 )
6624 }
6625
6626 #[test]
6627 fn test_suptitle() {
6628 Mpl::default()
6629 & suptitle("hello world").o("fontsize", "xx-small")
6630 | runner()
6631 }
6632
6633 #[test]
6634 fn test_supxlabel() {
6635 Mpl::default()
6636 & supxlabel("hello world").o("fontsize", "xx-small")
6637 | runner()
6638 }
6639
6640 #[test]
6641 fn test_supylabel() {
6642 Mpl::default()
6643 & supylabel("hello world").o("fontsize", "xx-small")
6644 | runner()
6645 }
6646
6647 #[test]
6648 fn test_make_grid() {
6649 Mpl::new_grid(3, 3, [opt("sharex", true), opt("sharey", true)])
6650 & focus_ax("AX[1, 1]")
6651 & plot([0.0, 1.0], [0.0, 1.0]).o("color", "C1")
6652 | runner()
6653 }
6654
6655 #[test]
6656 fn test_make_gridspec() {
6657 Mpl::new_gridspec(
6671 [
6672 opt("nrows", 3),
6673 opt("ncols", 3),
6674 opt("width_ratios", PyValue::list([1, 1, 2])),
6675 ],
6676 [
6677 GSPos::new(0..2, 0..2),
6678 GSPos::new(2..3, 0..2).sharex(Some(0)),
6679 GSPos::new(0..3, 2..3),
6680 ],
6681 )
6682 & focus_ax("AX[1]")
6683 & plot([0.0, 1.0], [0.0, 1.0]).o("color", "C1")
6684 | runner()
6685 }
6686
6687 #[test]
6688 fn test_tex_off() {
6689 Mpl::default()
6690 & tex_off()
6691 | runner()
6692 }
6693
6694 #[test]
6695 fn test_tex_on() {
6696 Mpl::default()
6697 & tex_on()
6698 | runner()
6699 }
6700
6701 #[test]
6702 fn test_text() {
6703 Mpl::default()
6704 & text(0.5, 0.5, "hello world").o("fontsize", "large")
6705 | runner()
6706 }
6707
6708 #[test]
6709 fn test_tick_params() {
6710 Mpl::default()
6711 & tick_params(Axis2::Both).o("color", "r")
6712 | runner()
6713 }
6714
6715 #[test]
6716 fn test_xtick_params() {
6717 Mpl::default()
6718 & xtick_params().o("color", "r")
6719 | runner()
6720 }
6721
6722 #[test]
6723 fn test_ytick_params() {
6724 Mpl::default()
6725 & xtick_params().o("color", "r")
6726 | runner()
6727 }
6728
6729 #[test]
6730 fn test_tick_params_eq() {
6731 assert_eq!(
6732 tick_params(Axis2::X).o("color", "r"),
6733 xtick_params().o("color", "r"),
6734 );
6735 assert_eq!(
6736 tick_params(Axis2::Y).o("color", "r"),
6737 ytick_params().o("color", "r"),
6738 );
6739 }
6740
6741 #[test]
6742 fn test_ticklabels() {
6743 Mpl::default()
6744 & ticklabels(Axis::X, [0.0, 1.0], ["x:zero", "x:one"])
6745 .o("fontsize", "small")
6746 & ticklabels(Axis::Y, [0.0, 1.0], ["y:zero", "y:one"])
6747 .o("fontsize", "small")
6748 | runner()
6749 }
6750
6751 #[test]
6752 fn test_ticklabels_data() {
6753 Mpl::default()
6754 & ticklabels_data(Axis::X, [(0.0, "x:zero"), (1.0, "x:one")])
6755 .o("fontsize", "small")
6756 & ticklabels_data(Axis::Y, [(0.0, "y:zero"), (1.0, "y:one")])
6757 .o("fontsize", "small")
6758 | runner()
6759 }
6760
6761 #[test]
6762 fn test_xticklabels() {
6763 Mpl::default()
6764 & xticklabels([0.0, 1.0], ["x:zero", "x:one"])
6765 .o("fontsize", "small")
6766 | runner()
6767 }
6768
6769 #[test]
6770 fn test_xticklabels_data() {
6771 Mpl::default()
6772 & xticklabels_data([(0.0, "x:zero"), (1.0, "x:one")])
6773 .o("fontsize", "small")
6774 | runner()
6775 }
6776
6777 #[test]
6778 fn test_yticklabels() {
6779 Mpl::default()
6780 & yticklabels([0.0, 1.0], ["y:zero", "y:one"])
6781 .o("fontsize", "small")
6782 | runner()
6783 }
6784
6785 #[test]
6786 fn test_yticklabels_data() {
6787 Mpl::default()
6788 & yticklabels_data([(0.0, "y:zero"), (1.0, "y:one")])
6789 .o("fontsize", "small")
6790 | runner()
6791 }
6792
6793 #[test]
6794 fn test_ticklabels_eq() {
6795 let normx =
6796 ticklabels(Axis::X, [0.0, 1.0], ["x:zero", "x:one"]);
6797 let normx_data =
6798 ticklabels_data(Axis::X, [(0.0, "x:zero"), (1.0, "x:one")]);
6799 let aliasx =
6800 xticklabels([0.0, 1.0], ["x:zero", "x:one"]);
6801 let aliasx_data =
6802 xticklabels_data([(0.0, "x:zero"), (1.0, "x:one")]);
6803 let normy =
6804 ticklabels(Axis::Y, [0.0, 1.0], ["y:zero", "y:one"]);
6805 let normy_data =
6806 ticklabels_data(Axis::Y, [(0.0, "y:zero"), (1.0, "y:one")]);
6807 let aliasy =
6808 yticklabels([0.0, 1.0], ["y:zero", "y:one"]);
6809 let aliasy_data =
6810 yticklabels_data([(0.0, "y:zero"), (1.0, "y:one")]);
6811 assert_eq!(normx, normx_data);
6812 assert_eq!(aliasx, aliasx_data);
6813 assert_eq!(normx, aliasx);
6814 assert_eq!(normy, normy_data);
6815 assert_eq!(aliasy, aliasy_data);
6816 assert_eq!(normy, aliasy);
6817 }
6818
6819 #[test]
6820 fn test_ticks() {
6821 Mpl::default()
6822 & ticks(Axis::X, [0.0, 1.0]).o("minor", true)
6823 & ticks(Axis::Y, [0.0, 2.0]).o("minor", true)
6824 | runner()
6825 }
6826
6827 #[test]
6828 fn test_xticks() {
6829 Mpl::default()
6830 & xticks([0.0, 1.0]).o("minor", true)
6831 | runner()
6832 }
6833
6834 #[test]
6835 fn test_yticks() {
6836 Mpl::default()
6837 & yticks([0.0, 2.0]).o("minor", true)
6838 | runner()
6839 }
6840
6841 #[test]
6842 fn test_ticks_eq() {
6843 let normx = ticks(Axis::X, [0.0, 1.0]);
6844 let aliasx = xticks([0.0, 1.0]);
6845 let normy = ticks(Axis::Y, [0.0, 2.0]);
6846 let aliasy = yticks([0.0, 2.0]);
6847 assert_eq!(normx, aliasx);
6848 assert_eq!(normy, aliasy);
6849 }
6850
6851 #[test]
6852 fn test_title() {
6853 Mpl::default()
6854 & title("hello world").o("fontsize", "large")
6855 | runner()
6856 }
6857
6858 #[test]
6859 fn test_tight_layout() {
6860 Mpl::new_grid(3, 3, [])
6861 & tight_layout().o("h_pad", 1.0).o("w_pad", 0.5)
6862 | runner()
6863 }
6864
6865 #[test]
6866 fn test_make_3d() {
6867 Mpl::new_3d([opt("elev", 50.0)])
6868 | runner()
6869 }
6870
6871 #[test]
6872 fn test_plot3() {
6873 Mpl::new_3d([])
6874 & plot3([0.0, 1.0], [0.0, 1.0], [0.0, 1.0]).o("marker", "D")
6875 | runner()
6876 }
6877
6878 #[test]
6879 fn test_plot3_data() {
6880 Mpl::new_3d([])
6881 & plot3_data([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]).o("marker", "D")
6882 | runner()
6883 }
6884
6885 #[test]
6886 fn test_plot3_eq() {
6887 assert_eq!(
6888 plot3([0.0, 1.0], [0.0, 1.0], [0.0, 1.0]).o("marker", "D"),
6889 plot3_data([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]).o("marker", "D"),
6890 )
6891 }
6892
6893 #[test]
6894 fn test_scatter3() {
6895 Mpl::new_3d([])
6896 & scatter3([0.0, 1.0], [0.0, 1.0], [0.0, 1.0]).o("marker", "D")
6897 | runner()
6898 }
6899
6900 #[test]
6901 fn test_scatter3_data() {
6902 Mpl::new_3d([])
6903 & scatter3_data([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]).o("marker", "D")
6904 | runner()
6905 }
6906
6907 #[test]
6908 fn test_scatter3_eq() {
6909 assert_eq!(
6910 scatter3([0.0, 1.0], [0.0, 1.0], [0.0, 1.0]).o("marker", "D"),
6911 scatter3_data([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]).o("marker", "D"),
6912 )
6913 }
6914
6915 #[test]
6916 fn test_quiver3() {
6917 Mpl::new_3d([])
6918 & quiver3(
6919 [0.0, 1.0],
6920 [0.0, 1.0],
6921 [0.0, 1.0],
6922 [1.0, 2.0],
6923 [1.0, 2.0],
6924 [1.0, 2.0],
6925 ).o("pivot", "middle")
6926 | runner()
6927 }
6928
6929 #[test]
6930 fn test_quiver3_data() {
6931 Mpl::new_3d([])
6932 & quiver3_data([
6933 (0.0, 0.0, 0.0, 1.0, 1.0, 1.0),
6934 (1.0, 1.0, 1.0, 2.0, 2.0, 2.0),
6935 ]).o("pivot", "middle")
6936 | runner()
6937 }
6938
6939 #[test]
6940 fn test_quiver3_triples() {
6941 Mpl::new_3d([])
6942 & quiver3_triples(
6943 [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
6944 [(1.0, 1.0, 1.0), (2.0, 2.0, 2.0)],
6945 ).o("pivot", "middle")
6946 | runner()
6947 }
6948
6949 #[test]
6950 fn test_quiver3_eq() {
6951 let norm = quiver3(
6952 [0.0, 1.0],
6953 [0.0, 1.0],
6954 [0.0, 1.0],
6955 [1.0, 2.0],
6956 [1.0, 2.0],
6957 [1.0, 2.0],
6958 ).o("pivot", "middle");
6959 let data = quiver3_data([
6960 (0.0, 0.0, 0.0, 1.0, 1.0, 1.0),
6961 (1.0, 1.0, 1.0, 2.0, 2.0, 2.0),
6962 ]).o("pivot", "middle");
6963 let triples = quiver3_triples(
6964 [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
6965 [(1.0, 1.0, 1.0), (2.0, 2.0, 2.0)],
6966 ).o("pivot", "middle");
6967 assert_eq!(norm, data);
6968 assert_eq!(norm, triples);
6969 }
6970
6971 #[test]
6972 fn test_surface() {
6973 Mpl::new_3d([])
6974 & surface(
6975 [[0.0, 1.0], [0.0, 1.0]],
6976 [[0.0, 0.0], [1.0, 1.0]],
6977 [[0.0, 1.0], [2.0, 3.0]],
6978 ).o("cmap", "rainbow")
6979 | runner()
6980 }
6981
6982 #[test]
6983 fn test_surface_data() {
6984 Mpl::new_3d([])
6985 & surface_data(
6986 [
6987 (0.0, 0.0, 0.0),
6988 (1.0, 0.0, 1.0),
6989 (0.0, 1.0, 2.0),
6990 (1.0, 1.0, 3.0),
6991 ],
6992 2,
6993 ).o("cmap", "rainbow")
6994 | runner()
6995 }
6996
6997 #[test]
6998 fn test_surface_flat() {
6999 Mpl::new_3d([])
7000 & surface_flat(
7001 [0.0, 1.0, 0.0, 1.0],
7002 [0.0, 0.0, 1.0, 1.0],
7003 [0.0, 1.0, 2.0, 3.0],
7004 2,
7005 ).o("cmap", "rainbow")
7006 | runner()
7007 }
7008
7009 #[test]
7010 fn test_surface_eq() {
7011 let norm = surface(
7012 [[0.0, 1.0], [0.0, 1.0]],
7013 [[0.0, 0.0], [1.0, 1.0]],
7014 [[0.0, 1.0], [2.0, 3.0]],
7015 ).o("cmap", "rainbow");
7016 let data = surface_data(
7017 [
7018 (0.0, 0.0, 0.0),
7019 (1.0, 0.0, 1.0),
7020 (0.0, 1.0, 2.0),
7021 (1.0, 1.0, 3.0),
7022 ],
7023 2,
7024 ).o("cmap", "rainbow");
7025 let flat = surface_flat(
7026 [0.0, 1.0, 0.0, 1.0],
7027 [0.0, 0.0, 1.0, 1.0],
7028 [0.0, 1.0, 2.0, 3.0],
7029 2,
7030 ).o("cmap", "rainbow");
7031 assert_eq!(norm, data);
7032 assert_eq!(norm, flat);
7033 }
7034
7035 #[test]
7036 fn test_trisurf() {
7037 Mpl::new_3d([])
7038 & trisurf(
7039 [0.0, 1.0, 0.0, 1.0],
7040 [0.0, 0.0, 1.0, 1.0],
7041 [0.0, 1.0, 2.0, 3.0],
7042 ).o("cmap", "rainbow")
7043 | runner()
7044 }
7045
7046 #[test]
7047 fn test_trisurf_data() {
7048 Mpl::new_3d([])
7049 & trisurf_data([
7050 (0.0, 0.0, 0.0),
7051 (1.0, 0.0, 1.0),
7052 (0.0, 1.0, 2.0),
7053 (1.0, 1.0, 3.0),
7054 ]).o("cmap", "rainbow")
7055 | runner()
7056 }
7057
7058 #[test]
7059 fn test_trisurf_eq() {
7060 let norm = trisurf(
7061 [0.0, 1.0, 0.0, 1.0],
7062 [0.0, 0.0, 1.0, 1.0],
7063 [0.0, 1.0, 2.0, 3.0],
7064 ).o("cmap", "rainbow");
7065 let data = trisurf_data([
7066 (0.0, 0.0, 0.0),
7067 (1.0, 0.0, 1.0),
7068 (0.0, 1.0, 2.0),
7069 (1.0, 1.0, 3.0),
7070 ]).o("cmap", "rainbow");
7071 assert_eq!(norm, data);
7072 }
7073
7074 #[test]
7075 fn test_view_init() {
7076 Mpl::new_3d([])
7077 & view_init(90.0, 0.0).o("roll", 45.0)
7078 | runner()
7079 }
7080
7081 #[test]
7082 fn test_zlabel() {
7083 Mpl::new_3d([])
7084 & zlabel("zlabel")
7085 | runner()
7086 }
7087
7088 #[test]
7089 fn test_zlim() {
7090 Mpl::new_3d([])
7091 & zlim(Some(-10.0), Some(15.0))
7092 | runner()
7093 }
7094
7095 #[test]
7096 fn test_zscale() {
7097 Mpl::new_3d([])
7098 & zscale(AxisScale::Log)
7099 | runner()
7100 }
7101
7102 #[test]
7103 fn test_zticklabels() {
7104 Mpl::new_3d([])
7105 & zticklabels([0.0, 1.0], ["zero", "one"]).o("minor", true)
7106 | runner()
7107 }
7108
7109 #[test]
7110 fn test_zticklabels_data() {
7111 Mpl::new_3d([])
7112 & zticklabels_data([(0.0, "zero"), (1.0, "one")]).o("minor", true)
7113 | runner()
7114 }
7115
7116 #[test]
7117 fn test_zticklabels_eq() {
7118 assert_eq!(
7119 zticklabels([0.0, 1.0], ["zero", "one"]).o("minor", true),
7120 zticklabels_data([(0.0, "zero"), (1.0, "one")]).o("minor", true),
7121 )
7122 }
7123
7124 #[test]
7125 fn test_zticks() {
7126 Mpl::new_3d([])
7127 & zticks([0.0, 1.0]).o("minor", true)
7128 | runner()
7129 }
7130}
7131