1use serde_json::Value;
22use crate::core::{
23 Matplotlib,
24 MatplotlibOpts,
25 Opt,
26 GSPos,
27 PyValue,
28 AsPy,
29 PRELUDE,
30 INIT,
31};
32
33#[derive(Clone, Debug, PartialEq, Eq)]
41pub struct Raw(pub String);
42
43impl Raw {
44 pub fn new(s: &str) -> Self { Self(s.into()) }
46}
47
48pub fn raw(s: &str) -> Raw { Raw::new(s) }
50
51impl Matplotlib for Raw {
52 fn is_prelude(&self) -> bool { false }
53
54 fn data(&self) -> Option<Value> { None }
55
56 fn py_cmd(&self) -> String { self.0.clone() }
57}
58
59#[derive(Clone, Debug, PartialEq, Eq)]
67pub struct Prelude(pub String);
68
69impl Prelude {
70 pub fn new(s: &str) -> Self { Self(s.into()) }
72}
73
74pub fn prelude(s: &str) -> Prelude { Prelude::new(s) }
76
77impl Matplotlib for Prelude {
78 fn is_prelude(&self) -> bool { true }
79
80 fn data(&self) -> Option<Value> { None }
81
82 fn py_cmd(&self) -> String { self.0.clone() }
83}
84
85#[derive(Copy, Clone, Debug, PartialEq, Eq)]
97pub struct DefPrelude;
98
99impl Matplotlib for DefPrelude {
100 fn is_prelude(&self) -> bool { true }
101
102 fn data(&self) -> Option<Value> { None }
103
104 fn py_cmd(&self) -> String { PRELUDE.into() }
105}
106
107#[derive(Copy, Clone, Debug, PartialEq, Eq)]
115pub struct DefInit;
116
117impl Matplotlib for DefInit {
118 fn is_prelude(&self) -> bool { false }
119
120 fn data(&self) -> Option<Value> { None }
121
122 fn py_cmd(&self) -> String { INIT.into() }
123}
124
125#[derive(Clone, Debug, PartialEq, Default)]
141pub struct Init3D {
142 pub opts: Vec<Opt>,
144}
145
146impl Init3D {
147 pub fn new() -> Self { Self { opts: Vec::new() } }
149}
150
151impl Matplotlib for Init3D {
152 fn is_prelude(&self) -> bool { false }
153
154 fn data(&self) -> Option<Value> { None }
155
156 fn py_cmd(&self) -> String {
157 format!("\
158 fig = plt.figure()\n\
159 ax = axes3d.Axes3D(fig, auto_add_to_figure=False{}{})\n\
160 fig.add_axes(ax)",
161 if self.opts.is_empty() { "" } else { ", " },
162 self.opts.as_py(),
163 )
164 }
165}
166
167impl MatplotlibOpts for Init3D {
168 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
169 self.opts.push((key, val).into());
170 self
171 }
172}
173
174#[derive(Clone, Debug, PartialEq)]
192pub struct InitGrid {
193 pub nrows: usize,
195 pub ncols: usize,
197 pub opts: Vec<Opt>,
199}
200
201impl InitGrid {
202 pub fn new(nrows: usize, ncols: usize) -> Self {
204 Self { nrows, ncols, opts: Vec::new() }
205 }
206}
207
208pub fn init_grid(nrows: usize, ncols: usize) -> InitGrid {
210 InitGrid::new(nrows, ncols)
211}
212
213impl Matplotlib for InitGrid {
214 fn is_prelude(&self) -> bool { false }
215
216 fn data(&self) -> Option<Value> { None }
217
218 fn py_cmd(&self) -> String {
219 format!("\
220 fig, AX = plt.subplots(nrows={}, ncols={}{}{})\n\
221 AX = AX.reshape(({}, {}))\n\
222 ax = AX[0, 0]",
223 self.nrows,
224 self.ncols,
225 if self.opts.is_empty() { "" } else { ", " },
226 self.opts.as_py(),
227 self.nrows,
228 self.ncols,
229 )
230 }
231}
232
233impl MatplotlibOpts for InitGrid {
234 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
235 self.opts.push((key, val).into());
236 self
237 }
238}
239
240#[derive(Clone, Debug, PartialEq)]
264pub struct InitGridSpec {
265 pub gridspec_kw: Vec<Opt>,
267 pub positions: Vec<GSPos>,
269}
270
271impl InitGridSpec {
272 pub fn new<I, P>(gridspec_kw: I, positions: P) -> Self
274 where
275 I: IntoIterator<Item = Opt>,
276 P: IntoIterator<Item = GSPos>,
277 {
278 Self {
279 gridspec_kw: gridspec_kw.into_iter().collect(),
280 positions: positions.into_iter().collect(),
281 }
282 }
283}
284
285pub fn init_gridspec<I, P>(gridspec_kw: I, positions: P) -> InitGridSpec
287where
288 I: IntoIterator<Item = Opt>,
289 P: IntoIterator<Item = GSPos>,
290{
291 InitGridSpec::new(gridspec_kw, positions)
292}
293
294impl Matplotlib for InitGridSpec {
295 fn is_prelude(&self) -> bool { false }
296
297 fn data(&self) -> Option<Value> { None }
298
299 fn py_cmd(&self) -> String {
300 let mut code =
301 format!("\
302 fig = plt.figure()\n\
303 gs = fig.add_gridspec({})\n\
304 AX = np.array([\n",
305 self.gridspec_kw.as_py(),
306 );
307 for GSPos { i, j, sharex: _, sharey: _ } in self.positions.iter() {
308 code.push_str(
309 &format!(" fig.add_subplot(gs[{}:{}, {}:{}]),\n",
310 i.start, i.end, j.start, j.end,
311 )
312 );
313 }
314 code.push_str("])\n");
315 let iter = self.positions.iter().enumerate();
316 for (k, GSPos { i: _, j: _, sharex, sharey }) in iter {
317 if let Some(x) = sharex {
318 code.push_str(&format!("AX[{}].sharex(AX[{}])\n", k, x));
319 }
320 if let Some(y) = sharey {
321 code.push_str(&format!("AX[{}].sharey(AX[{}])\n", k, y));
322 }
323 }
324 code.push_str("ax = AX[0]\n");
325 code
326 }
327}
328
329impl MatplotlibOpts for InitGridSpec {
330 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
331 self.gridspec_kw.push((key, val).into());
332 self
333 }
334}
335
336#[derive(Clone, Debug, PartialEq)]
350pub struct RcParam {
351 pub key: String,
353 pub val: PyValue,
355}
356
357impl RcParam {
358 pub fn new<T: Into<PyValue>>(key: &str, val: T) -> Self {
360 Self { key: key.into(), val: val.into() }
361 }
362}
363
364pub fn rcparam<T: Into<PyValue>>(key: &str, val: T) -> RcParam {
366 RcParam::new(key, val)
367}
368
369impl Matplotlib for RcParam {
370 fn is_prelude(&self) -> bool { false }
371
372 fn data(&self) -> Option<Value> { None }
373
374 fn py_cmd(&self) -> String {
375 format!("plt.rcParams[\"{}\"] = {}", self.key, self.val.as_py())
376 }
377}
378
379#[derive(Copy, Clone, Debug, PartialEq, Eq)]
389pub struct TeX(pub bool);
390
391impl TeX {
392 pub fn on() -> Self { Self(true) }
394
395 pub fn off() -> Self { Self(false) }
397}
398
399pub fn tex_on() -> TeX { TeX(true) }
401
402pub fn tex_off() -> TeX { TeX(false) }
404
405impl Matplotlib for TeX {
406 fn is_prelude(&self) -> bool { true }
407
408 fn data(&self) -> Option<Value> { None }
409
410 fn py_cmd(&self) -> String {
411 format!("plt.rcParams[\"text.usetex\"] = {}", self.0.as_py())
412 }
413}
414
415#[derive(Clone, Debug, PartialEq, Eq)]
425pub struct FocusAx(pub String);
426
427impl FocusAx {
428 pub fn new(expr: &str) -> Self { Self(expr.into()) }
430}
431
432pub fn focus_ax(expr: &str) -> FocusAx { FocusAx::new(expr) }
434
435impl Matplotlib for FocusAx {
436 fn is_prelude(&self) -> bool { false }
437
438 fn data(&self) -> Option<Value> { None }
439
440 fn py_cmd(&self) -> String { format!("ax = {}", self.0) }
441}
442
443#[derive(Clone, Debug, PartialEq, Eq)]
453pub struct FocusFig(pub String);
454
455impl FocusFig {
456 pub fn new(expr: &str) -> Self { Self(expr.into()) }
458}
459
460pub fn focus_fig(expr: &str) -> FocusFig { FocusFig::new(expr) }
462
463impl Matplotlib for FocusFig {
464 fn is_prelude(&self) -> bool { false }
465
466 fn data(&self) -> Option<Value> { None }
467
468 fn py_cmd(&self) -> String { format!("fig = {}", self.0) }
469}
470
471#[derive(Clone, Debug, PartialEq, Eq)]
481pub struct FocusCBar(pub String);
482
483impl FocusCBar {
484 pub fn new(expr: &str) -> Self { Self(expr.into()) }
486}
487
488pub fn focus_cbar(expr: &str) -> FocusCBar { FocusCBar::new(expr) }
490
491impl Matplotlib for FocusCBar {
492 fn is_prelude(&self) -> bool { false }
493
494 fn data(&self) -> Option<Value> { None }
495
496 fn py_cmd(&self) -> String { format!("cbar = {}", self.0) }
497}
498
499#[derive(Clone, Debug, PartialEq, Eq)]
509pub struct FocusIm(pub String);
510
511impl FocusIm {
512 pub fn new(expr: &str) -> Self { Self(expr.into()) }
514}
515
516pub fn focus_im(expr: &str) -> FocusIm { FocusIm::new(expr) }
518
519impl Matplotlib for FocusIm {
520 fn is_prelude(&self) -> bool { false }
521
522 fn data(&self) -> Option<Value> { None }
523
524 fn py_cmd(&self) -> String { format!("im = {}", self.0) }
525}
526
527#[derive(Clone, Debug, PartialEq)]
537pub struct Plot {
538 pub x: Vec<f64>,
540 pub y: Vec<f64>,
542 pub opts: Vec<Opt>,
544}
545
546impl Plot {
547 pub fn new<X, Y>(x: X, y: Y) -> Self
549 where
550 X: IntoIterator<Item = f64>,
551 Y: IntoIterator<Item = f64>,
552 {
553 Self {
554 x: x.into_iter().collect(),
555 y: y.into_iter().collect(),
556 opts: Vec::new(),
557 }
558 }
559
560 pub fn new_pairs<I>(data: I) -> Self
562 where I: IntoIterator<Item = (f64, f64)>
563 {
564 let (x, y): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
565 Self { x, y, opts: Vec::new() }
566 }
567}
568
569pub fn plot<X, Y>(x: X, y: Y) -> Plot
571where
572 X: IntoIterator<Item = f64>,
573 Y: IntoIterator<Item = f64>,
574{
575 Plot::new(x, y)
576}
577
578pub fn plot_pairs<I>(data: I) -> Plot
580where I: IntoIterator<Item = (f64, f64)>
581{
582 Plot::new_pairs(data)
583}
584
585impl Matplotlib for Plot {
586 fn is_prelude(&self) -> bool { false }
587
588 fn data(&self) -> Option<Value> {
589 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
590 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
591 Some(Value::Array(vec![x.into(), y.into()]))
592 }
593
594 fn py_cmd(&self) -> String {
595 format!("ax.plot(data[0], data[1]{}{})",
596 if self.opts.is_empty() { "" } else { ", " },
597 self.opts.as_py(),
598 )
599 }
600}
601
602impl MatplotlibOpts for Plot {
603 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
604 self.opts.push((key, val).into());
605 self
606 }
607}
608
609#[derive(Clone, Debug, PartialEq)]
619pub struct Hist {
620 pub data: Vec<f64>,
622 pub opts: Vec<Opt>,
624}
625
626impl Hist {
627 pub fn new<I>(data: I) -> Self
629 where I: IntoIterator<Item = f64>
630 {
631 let data: Vec<f64> = data.into_iter().collect();
632 Self { data, opts: Vec::new() }
633 }
634}
635
636pub fn hist<I>(data: I) -> Hist
638where I: IntoIterator<Item = f64>
639{
640 Hist::new(data)
641}
642
643impl Matplotlib for Hist {
644 fn is_prelude(&self) -> bool { false }
645
646 fn data(&self) -> Option<Value> {
647 let data: Vec<Value> =
648 self.data.iter().copied().map(Value::from).collect();
649 Some(Value::Array(data))
650 }
651
652 fn py_cmd(&self) -> String {
653 format!("ax.hist(data{}{})",
654 if self.opts.is_empty() { "" } else { ", " },
655 self.opts.as_py(),
656 )
657 }
658}
659
660impl MatplotlibOpts for Hist {
661 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
662 self.opts.push((key, val).into());
663 self
664 }
665}
666
667#[derive(Clone, Debug, PartialEq)]
677pub struct Hist2d {
678 pub x: Vec<f64>,
680 pub y: Vec<f64>,
682 pub opts: Vec<Opt>,
684}
685
686impl Hist2d {
687 pub fn new<X, Y>(x: X, y: Y) -> Self
689 where
690 X: IntoIterator<Item = f64>,
691 Y: IntoIterator<Item = f64>,
692 {
693 let x: Vec<f64> = x.into_iter().collect();
694 let y: Vec<f64> = y.into_iter().collect();
695 Self { x, y, opts: Vec::new() }
696 }
697
698 pub fn new_pairs<I>(data: I) -> Self
700 where I: IntoIterator<Item = (f64, f64)>
701 {
702 let (x, y): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
703 Self { x, y, opts: Vec::new() }
704 }
705}
706
707pub fn hist2d<X, Y>(x: X, y: Y) -> Hist2d
709where
710 X: IntoIterator<Item = f64>,
711 Y: IntoIterator<Item = f64>,
712{
713 Hist2d::new(x, y)
714}
715
716pub fn hist2d_pairs<I>(data: I) -> Hist2d
718where I: IntoIterator<Item = (f64, f64)>
719{
720 Hist2d::new_pairs(data)
721}
722
723impl Matplotlib for Hist2d {
724 fn is_prelude(&self) -> bool { false }
725
726 fn data(&self) -> Option<Value> {
727 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
728 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
729 Some(Value::Array(vec![x.into(), y.into()]))
730 }
731
732 fn py_cmd(&self) -> String {
733 format!("ax.hist2d(data[0], data[1]{}{})",
734 if self.opts.is_empty() { "" } else { ", " },
735 self.opts.as_py(),
736 )
737 }
738}
739
740impl MatplotlibOpts for Hist2d {
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 Scatter {
758 pub x: Vec<f64>,
760 pub y: Vec<f64>,
762 pub opts: Vec<Opt>,
764}
765
766impl Scatter {
767 pub fn new<X, Y>(x: X, y: Y) -> Self
769 where
770 X: IntoIterator<Item = f64>,
771 Y: IntoIterator<Item = f64>,
772 {
773 Self {
774 x: x.into_iter().collect(),
775 y: y.into_iter().collect(),
776 opts: Vec::new(),
777 }
778 }
779
780 pub fn new_pairs<I>(data: I) -> Self
782 where I: IntoIterator<Item = (f64, f64)>
783 {
784 let (x, y): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
785 Self { x, y, opts: Vec::new() }
786 }
787}
788
789pub fn scatter<X, Y>(x: X, y: Y) -> Scatter
791where
792 X: IntoIterator<Item = f64>,
793 Y: IntoIterator<Item = f64>,
794{
795 Scatter::new(x, y)
796}
797
798pub fn scatter_pairs<I>(data: I) -> Scatter
800where I: IntoIterator<Item = (f64, f64)>
801{
802 Scatter::new_pairs(data)
803}
804
805impl Matplotlib for Scatter {
806 fn is_prelude(&self) -> bool { false }
807
808 fn data(&self) -> Option<Value> {
809 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
810 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
811 Some(Value::Array(vec![x.into(), y.into()]))
812 }
813
814 fn py_cmd(&self) -> String {
815 format!("ax.scatter(data[0], data[1]{}{})",
816 if self.opts.is_empty() { "" } else { ", " },
817 self.opts.as_py(),
818 )
819 }
820}
821
822impl MatplotlibOpts for Scatter {
823 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
824 self.opts.push((key, val).into());
825 self
826 }
827}
828
829#[derive(Clone, Debug, PartialEq)]
839pub struct Quiver {
840 pub x: Vec<f64>,
842 pub y: Vec<f64>,
844 pub vx: Vec<f64>,
846 pub vy: Vec<f64>,
848 pub opts: Vec<Opt>,
850}
851
852impl Quiver {
853 pub fn new<X, Y, VX, VY>(x: X, y: Y, vx: VX, vy: VY) -> Self
855 where
856 X: IntoIterator<Item = f64>,
857 Y: IntoIterator<Item = f64>,
858 VX: IntoIterator<Item = f64>,
859 VY: IntoIterator<Item = f64>,
860 {
861 Self {
862 x: x.into_iter().collect(),
863 y: y.into_iter().collect(),
864 vx: vx.into_iter().collect(),
865 vy: vy.into_iter().collect(),
866 opts: Vec::new(),
867 }
868 }
869
870 pub fn new_pairs<I, VI>(xy: I, vxy: VI) -> Self
873 where
874 I: IntoIterator<Item = (f64, f64)>,
875 VI: IntoIterator<Item = (f64, f64)>,
876 {
877 let (x, y) = xy.into_iter().unzip();
878 let (vx, vy) = vxy.into_iter().unzip();
879 Self { x, y, vx, vy, opts: Vec::new() }
880 }
881
882 pub fn new_data<I>(data: I) -> Self
886 where I: IntoIterator<Item = (f64, f64, f64, f64)>
887 {
888 let (((x, y), vx), vy) = data.into_iter().map(assoc).unzip();
889 Self { x, y, vx, vy, opts: Vec::new() }
890 }
891}
892
893pub fn quiver<X, Y, VX, VY>(x: X, y: Y, vx: VX, vy: VY) -> Quiver
895where
896 X: IntoIterator<Item = f64>,
897 Y: IntoIterator<Item = f64>,
898 VX: IntoIterator<Item = f64>,
899 VY: IntoIterator<Item = f64>,
900{
901 Quiver::new(x, y, vx, vy)
902}
903
904pub fn quiver_pairs<I, VI>(xy: I, vxy: VI) -> Quiver
907where
908 I: IntoIterator<Item = (f64, f64)>,
909 VI: IntoIterator<Item = (f64, f64)>,
910{
911 Quiver::new_pairs(xy, vxy)
912}
913
914pub fn quiver_data<I>(data: I) -> Quiver
918where I: IntoIterator<Item = (f64, f64, f64, f64)>
919{
920 Quiver::new_data(data)
921}
922
923impl Matplotlib for Quiver {
924 fn is_prelude(&self) -> bool { false }
925
926 fn data(&self) -> Option<Value> {
927 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
928 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
929 let vx: Vec<Value> = self.vx.iter().copied().map(Value::from).collect();
930 let vy: Vec<Value> = self.vy.iter().copied().map(Value::from).collect();
931 Some(Value::Array(vec![x.into(), y.into(), vx.into(), vy.into()]))
932 }
933
934 fn py_cmd(&self) -> String {
935 format!("ax.quiver(data[0], data[1], data[2], data[3]{}{})",
936 if self.opts.is_empty() { "" } else { ", " },
937 self.opts.as_py(),
938 )
939 }
940}
941
942impl MatplotlibOpts for Quiver {
943 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
944 self.opts.push((key, val).into());
945 self
946 }
947}
948
949#[derive(Clone, Debug, PartialEq)]
959pub struct Bar {
960 pub x: Vec<f64>,
962 pub y: Vec<f64>,
964 pub opts: Vec<Opt>,
966}
967
968impl Bar {
969 pub fn new<X, Y>(x: X, y: Y) -> Self
971 where
972 X: IntoIterator<Item = f64>,
973 Y: IntoIterator<Item = f64>,
974 {
975 Self {
976 x: x.into_iter().collect(),
977 y: y.into_iter().collect(),
978 opts: Vec::new(),
979 }
980 }
981
982 pub fn new_pairs<I>(data: I) -> Self
984 where I: IntoIterator<Item = (f64, f64)>
985 {
986 let (x, y): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
987 Self { x, y, opts: Vec::new() }
988 }
989}
990
991pub fn bar<X, Y>(x: X, y: Y) -> Bar
993where
994 X: IntoIterator<Item = f64>,
995 Y: IntoIterator<Item = f64>,
996{
997 Bar::new(x, y)
998}
999
1000pub fn bar_pairs<I>(data: I) -> Bar
1002where I: IntoIterator<Item = (f64, f64)>
1003{
1004 Bar::new_pairs(data)
1005}
1006
1007impl Matplotlib for Bar {
1008 fn is_prelude(&self) -> bool { false }
1009
1010 fn data(&self) -> Option<Value> {
1011 let x: Vec<Value> =
1012 self.x.iter().copied().map(Value::from).collect();
1013 let y: Vec<Value> =
1014 self.y.iter().copied().map(Value::from).collect();
1015 Some(Value::Array(vec![x.into(), y.into()]))
1016 }
1017
1018 fn py_cmd(&self) -> String {
1019 format!("ax.bar(data[0], data[1]{}{})",
1020 if self.opts.is_empty() { "" } else { ", " },
1021 self.opts.as_py(),
1022 )
1023 }
1024}
1025
1026impl MatplotlibOpts for Bar {
1027 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1028 self.opts.push((key, val).into());
1029 self
1030 }
1031}
1032
1033#[derive(Clone, Debug, PartialEq)]
1043pub struct BarH {
1044 pub y: Vec<f64>,
1046 pub w: Vec<f64>,
1048 pub opts: Vec<Opt>,
1050}
1051
1052impl BarH {
1053 pub fn new<Y, W>(y: Y, w: W) -> Self
1055 where
1056 Y: IntoIterator<Item = f64>,
1057 W: IntoIterator<Item = f64>,
1058 {
1059 Self {
1060 y: y.into_iter().collect(),
1061 w: w.into_iter().collect(),
1062 opts: Vec::new(),
1063 }
1064 }
1065
1066 pub fn new_pairs<I>(data: I) -> Self
1068 where I: IntoIterator<Item = (f64, f64)>
1069 {
1070 let (y, w): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
1071 Self { y, w, opts: Vec::new() }
1072 }
1073}
1074
1075pub fn barh<Y, W>(y: Y, w: W) -> BarH
1077where
1078 Y: IntoIterator<Item = f64>,
1079 W: IntoIterator<Item = f64>,
1080{
1081 BarH::new(y, w)
1082}
1083
1084pub fn barh_pairs<I>(data: I) -> BarH
1086where I: IntoIterator<Item = (f64, f64)>
1087{
1088 BarH::new_pairs(data)
1089}
1090
1091impl Matplotlib for BarH {
1092 fn is_prelude(&self) -> bool { false }
1093
1094 fn data(&self) -> Option<Value> {
1095 let y: Vec<Value> =
1096 self.y.iter().copied().map(Value::from).collect();
1097 let w: Vec<Value> =
1098 self.w.iter().copied().map(Value::from).collect();
1099 Some(Value::Array(vec![y.into(), w.into()]))
1100 }
1101
1102 fn py_cmd(&self) -> String {
1103 format!("ax.barh(data[0], data[1]{}{})",
1104 if self.opts.is_empty() { "" } else { ", " },
1105 self.opts.as_py(),
1106 )
1107 }
1108}
1109
1110impl MatplotlibOpts for BarH {
1111 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1112 self.opts.push((key, val).into());
1113 self
1114 }
1115}
1116
1117#[derive(Clone, Debug, PartialEq)]
1127pub struct Errorbar {
1128 pub x: Vec<f64>,
1130 pub y: Vec<f64>,
1132 pub e: Vec<f64>,
1134 pub opts: Vec<Opt>,
1136}
1137
1138impl Errorbar {
1139 pub fn new<X, Y, E>(x: X, y: Y, e: E) -> Self
1141 where
1142 X: IntoIterator<Item = f64>,
1143 Y: IntoIterator<Item = f64>,
1144 E: IntoIterator<Item = f64>,
1145 {
1146 Self {
1147 x: x.into_iter().collect(),
1148 y: y.into_iter().collect(),
1149 e: e.into_iter().collect(),
1150 opts: Vec::new(),
1151 }
1152 }
1153
1154 pub fn new_data<I>(data: I) -> Self
1156 where I: IntoIterator<Item = (f64, f64, f64)>
1157 {
1158 let ((x, y), e) = data.into_iter().map(assoc).unzip();
1159 Self { x, y, e, opts: Vec::new() }
1160 }
1161}
1162
1163pub fn errorbar<X, Y, E>(x: X, y: Y, e: E) -> Errorbar
1165where
1166 X: IntoIterator<Item = f64>,
1167 Y: IntoIterator<Item = f64>,
1168 E: IntoIterator<Item = f64>,
1169{
1170 Errorbar::new(x, y, e)
1171}
1172
1173pub fn errorbar_data<I>(data: I) -> Errorbar
1175where I: IntoIterator<Item = (f64, f64, f64)>
1176{
1177 Errorbar::new_data(data)
1178}
1179
1180impl Matplotlib for Errorbar {
1181 fn is_prelude(&self) -> bool { false }
1182
1183 fn data(&self) -> Option<Value> {
1184 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1185 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1186 let e: Vec<Value> = self.e.iter().copied().map(Value::from).collect();
1187 Some(Value::Array(vec![x.into(), y.into(), e.into()]))
1188 }
1189
1190 fn py_cmd(&self) -> String {
1191 format!("ax.errorbar(data[0], data[1], data[2]{}{})",
1192 if self.opts.is_empty() { "" } else { ", " },
1193 self.opts.as_py(),
1194 )
1195 }
1196}
1197
1198impl MatplotlibOpts for Errorbar {
1199 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1200 self.opts.push((key, val).into());
1201 self
1202 }
1203}
1204
1205impl From<FillBetween> for Errorbar {
1207 fn from(fill_between: FillBetween) -> Self {
1208 let FillBetween { x, mut y1, mut y2, opts } = fill_between;
1209 y1.iter_mut()
1210 .zip(y2.iter_mut())
1211 .for_each(|(y1k, y2k)| {
1212 let y1 = *y1k;
1213 let y2 = *y2k;
1214 *y1k = 0.5 * (y1 + y2);
1215 *y2k = 0.5 * (y1 - y2).abs();
1216 });
1217 Self { x, y: y1, e: y2, opts }
1218 }
1219}
1220
1221#[derive(Clone, Debug, PartialEq)]
1231pub struct Errorbar2 {
1232 pub x: Vec<f64>,
1234 pub y: Vec<f64>,
1236 pub e_neg: Vec<f64>,
1238 pub e_pos: Vec<f64>,
1240 pub opts: Vec<Opt>,
1242}
1243
1244impl Errorbar2 {
1245 pub fn new<X, Y, E1, E2>(x: X, y: Y, e_neg: E1, e_pos: E2) -> Self
1247 where
1248 X: IntoIterator<Item = f64>,
1249 Y: IntoIterator<Item = f64>,
1250 E1: IntoIterator<Item = f64>,
1251 E2: IntoIterator<Item = f64>,
1252 {
1253 Self {
1254 x: x.into_iter().collect(),
1255 y: y.into_iter().collect(),
1256 e_neg: e_neg.into_iter().collect(),
1257 e_pos: e_pos.into_iter().collect(),
1258 opts: Vec::new(),
1259 }
1260 }
1261
1262 pub fn new_data<I>(data: I) -> Self
1264 where I: IntoIterator<Item = (f64, f64, f64, f64)>
1265 {
1266 let (((x, y), e_neg), e_pos) =
1267 data.into_iter().map(assoc).unzip();
1268 Self { x, y, e_neg, e_pos, opts: Vec::new() }
1269 }
1270}
1271
1272pub fn errorbar2<X, Y, E1, E2>(x: X, y: Y, e_neg: E1, e_pos: E2) -> Errorbar2
1274where
1275 X: IntoIterator<Item = f64>,
1276 Y: IntoIterator<Item = f64>,
1277 E1: IntoIterator<Item = f64>,
1278 E2: IntoIterator<Item = f64>,
1279{
1280 Errorbar2::new(x, y, e_neg, e_pos)
1281}
1282
1283pub fn errorbar2_data<I>(data: I) -> Errorbar2
1285where I: IntoIterator<Item = (f64, f64, f64, f64)>
1286{
1287 Errorbar2::new_data(data)
1288}
1289
1290impl Matplotlib for Errorbar2 {
1291 fn is_prelude(&self) -> bool { false }
1292
1293 fn data(&self) -> Option<Value> {
1294 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1295 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1296 let e_neg: Vec<Value> =
1297 self.e_neg.iter().copied().map(Value::from).collect();
1298 let e_pos: Vec<Value> =
1299 self.e_pos.iter().copied().map(Value::from).collect();
1300 Some(Value::Array(
1301 vec![x.into(), y.into(), e_neg.into(), e_pos.into()]))
1302 }
1303
1304 fn py_cmd(&self) -> String {
1305 format!("ax.errorbar(data[0], data[1], [data[2], data[3]]{}{})",
1306 if self.opts.is_empty() { "" } else { ", " },
1307 self.opts.as_py(),
1308 )
1309 }
1310}
1311
1312impl MatplotlibOpts for Errorbar2 {
1313 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1314 self.opts.push((key, val).into());
1315 self
1316 }
1317}
1318
1319struct Chunks<I, T>
1320where I: Iterator<Item = T>
1321{
1322 chunksize: usize,
1323 buflen: usize,
1324 buf: Vec<T>,
1325 iter: I,
1326}
1327
1328impl<I, T> Chunks<I, T>
1329where I: Iterator<Item = T>
1330{
1331 fn new(iter: I, chunksize: usize) -> Self {
1332 if chunksize == 0 { panic!("chunk size cannot be zero"); }
1333 Self {
1334 chunksize,
1335 buflen: 0,
1336 buf: Vec::with_capacity(chunksize),
1337 iter,
1338 }
1339 }
1340}
1341
1342impl<I, T> Iterator for Chunks<I, T>
1343where I: Iterator<Item = T>
1344{
1345 type Item = Vec<T>;
1346
1347 fn next(&mut self) -> Option<Self::Item> {
1348 loop {
1349 if let Some(item) = self.iter.next() {
1350 self.buf.push(item);
1351 self.buflen += 1;
1352 if self.buflen == self.chunksize {
1353 let mut bufswap = Vec::with_capacity(self.chunksize);
1354 std::mem::swap(&mut bufswap, &mut self.buf);
1355 self.buflen = 0;
1356 return Some(bufswap);
1357 } else {
1358 continue;
1359 }
1360 } else if self.buflen > 0 {
1361 let mut bufswap = Vec::with_capacity(0);
1362 std::mem::swap(&mut bufswap, &mut self.buf);
1363 self.buflen = 0;
1364 return Some(bufswap);
1365 } else {
1366 return None;
1367 }
1368 }
1369 }
1370}
1371
1372
1373#[derive(Clone, Debug, PartialEq)]
1383pub struct Boxplot {
1384 pub data: Vec<Vec<f64>>,
1386 pub opts: Vec<Opt>,
1388}
1389
1390impl Boxplot {
1391 pub fn new<I, J>(data: I) -> Self
1393 where
1394 I: IntoIterator<Item = J>,
1395 J: IntoIterator<Item = f64>,
1396 {
1397 let data: Vec<Vec<f64>> =
1398 data.into_iter()
1399 .map(|row| row.into_iter().collect())
1400 .collect();
1401 Self { data, opts: Vec::new() }
1402 }
1403
1404 pub fn new_flat<I>(data: I, size: usize) -> Self
1412 where I: IntoIterator<Item = f64>
1413 {
1414 if size == 0 { panic!("data set size cannot be zero"); }
1415 let data: Vec<Vec<f64>> =
1416 Chunks::new(data.into_iter(), size)
1417 .collect();
1418 Self { data, opts: Vec::new() }
1419 }
1420}
1421
1422pub fn boxplot<I, J>(data: I) -> Boxplot
1424where
1425 I: IntoIterator<Item = J>,
1426 J: IntoIterator<Item = f64>,
1427{
1428 Boxplot::new(data)
1429}
1430
1431pub fn boxplot_flat<I>(data: I, size: usize) -> Boxplot
1439where I: IntoIterator<Item = f64>
1440{
1441 Boxplot::new_flat(data, size)
1442}
1443
1444impl Matplotlib for Boxplot {
1445 fn is_prelude(&self) -> bool { false }
1446
1447 fn data(&self) -> Option<Value> {
1448 let data: Vec<Value> =
1449 self.data.iter()
1450 .map(|row| {
1451 let row: Vec<Value> =
1452 row.iter().copied().map(Value::from).collect();
1453 Value::Array(row)
1454 })
1455 .collect();
1456 Some(Value::Array(data))
1457 }
1458
1459 fn py_cmd(&self) -> String {
1460 format!("ax.boxplot(data{}{})",
1461 if self.opts.is_empty() { "" } else { ", " },
1462 self.opts.as_py(),
1463 )
1464 }
1465}
1466
1467impl MatplotlibOpts for Boxplot {
1468 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1469 self.opts.push((key, val).into());
1470 self
1471 }
1472}
1473
1474#[derive(Clone, Debug, PartialEq)]
1484pub struct Violinplot {
1485 pub data: Vec<Vec<f64>>,
1487 pub opts: Vec<Opt>,
1489}
1490
1491impl Violinplot {
1492 pub fn new<I, J>(data: I) -> Self
1494 where
1495 I: IntoIterator<Item = J>,
1496 J: IntoIterator<Item = f64>,
1497 {
1498 let data: Vec<Vec<f64>> =
1499 data.into_iter()
1500 .map(|row| row.into_iter().collect())
1501 .collect();
1502 Self { data, opts: Vec::new() }
1503 }
1504
1505 pub fn new_flat<I>(data: I, size: usize) -> Self
1513 where I: IntoIterator<Item = f64>
1514 {
1515 if size == 0 { panic!("data set size cannot be zero"); }
1516 let data: Vec<Vec<f64>> =
1517 Chunks::new(data.into_iter(), size)
1518 .collect();
1519 Self { data, opts: Vec::new() }
1520 }
1521}
1522
1523pub fn violinplot<I, J>(data: I) -> Violinplot
1525where
1526 I: IntoIterator<Item = J>,
1527 J: IntoIterator<Item = f64>,
1528{
1529 Violinplot::new(data)
1530}
1531
1532pub fn violinplot_flat<I>(data: I, size: usize) -> Violinplot
1540where I: IntoIterator<Item = f64>
1541{
1542 Violinplot::new_flat(data, size)
1543}
1544
1545impl Matplotlib for Violinplot {
1546 fn is_prelude(&self) -> bool { false }
1547
1548 fn data(&self) -> Option<Value> {
1549 let data: Vec<Value> =
1550 self.data.iter()
1551 .map(|row| {
1552 let row: Vec<Value> =
1553 row.iter().copied().map(Value::from).collect();
1554 Value::Array(row)
1555 })
1556 .collect();
1557 Some(Value::Array(data))
1558 }
1559
1560 fn py_cmd(&self) -> String {
1561 format!("ax.violinplot(data{}{})",
1562 if self.opts.is_empty() { "" } else { ", " },
1563 self.opts.as_py(),
1564 )
1565 }
1566}
1567
1568impl MatplotlibOpts for Violinplot {
1569 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1570 self.opts.push((key, val).into());
1571 self
1572 }
1573}
1574
1575#[derive(Clone, Debug, PartialEq)]
1590pub struct Contour {
1591 pub x: Vec<f64>,
1593 pub y: Vec<f64>,
1595 pub z: Vec<Vec<f64>>,
1599 pub opts: Vec<Opt>,
1601}
1602
1603impl Contour {
1604 pub fn new<X, Y, ZI, ZJ>(x: X, y: Y, z: ZI) -> Self
1606 where
1607 X: IntoIterator<Item = f64>,
1608 Y: IntoIterator<Item = f64>,
1609 ZI: IntoIterator<Item = ZJ>,
1610 ZJ: IntoIterator<Item = f64>,
1611 {
1612 let x: Vec<f64> = x.into_iter().collect();
1613 let y: Vec<f64> = y.into_iter().collect();
1614 let z: Vec<Vec<f64>> =
1615 z.into_iter()
1616 .map(|row| row.into_iter().collect())
1617 .collect();
1618 Self { x, y, z, opts: Vec::new() }
1619 }
1620
1621 pub fn new_flat<X, Y, Z>(x: X, y: Y, z: Z) -> Self
1626 where
1627 X: IntoIterator<Item = f64>,
1628 Y: IntoIterator<Item = f64>,
1629 Z: IntoIterator<Item = f64>,
1630 {
1631 let x: Vec<f64> = x.into_iter().collect();
1632 if x.is_empty() { panic!("x-coordinate array cannot be empty"); }
1633 let y: Vec<f64> = y.into_iter().collect();
1634 let z: Vec<Vec<f64>> =
1635 Chunks::new(z.into_iter(), x.len())
1636 .collect();
1637 Self { x, y, z, opts: Vec::new() }
1638 }
1639}
1640
1641pub fn contour<X, Y, ZI, ZJ>(x: X, y: Y, z: ZI) -> Contour
1643where
1644 X: IntoIterator<Item = f64>,
1645 Y: IntoIterator<Item = f64>,
1646 ZI: IntoIterator<Item = ZJ>,
1647 ZJ: IntoIterator<Item = f64>,
1648{
1649 Contour::new(x, y, z)
1650}
1651
1652pub fn contour_flat<X, Y, Z>(x: X, y: Y, z: Z) -> Contour
1657where
1658 X: IntoIterator<Item = f64>,
1659 Y: IntoIterator<Item = f64>,
1660 Z: IntoIterator<Item = f64>,
1661{
1662 Contour::new_flat(x, y, z)
1663}
1664
1665impl Matplotlib for Contour {
1666 fn is_prelude(&self) -> bool { false }
1667
1668 fn data(&self) -> Option<Value> {
1669 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1670 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1671 let z: Vec<Value> =
1672 self.z.iter()
1673 .map(|row| {
1674 let row: Vec<Value> =
1675 row.iter().copied().map(Value::from).collect();
1676 Value::Array(row)
1677 })
1678 .collect();
1679 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
1680 }
1681
1682 fn py_cmd(&self) -> String {
1683 format!("im = ax.contour(data[0], data[1], data[2]{}{})",
1684 if self.opts.is_empty() { "" } else { ", " },
1685 self.opts.as_py(),
1686 )
1687 }
1688}
1689
1690impl MatplotlibOpts for Contour {
1691 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1692 self.opts.push((key, val).into());
1693 self
1694 }
1695}
1696
1697#[derive(Clone, Debug, PartialEq)]
1712pub struct Contourf {
1713 pub x: Vec<f64>,
1715 pub y: Vec<f64>,
1717 pub z: Vec<Vec<f64>>,
1721 pub opts: Vec<Opt>,
1723}
1724
1725impl Contourf {
1726 pub fn new<X, Y, ZI, ZJ>(x: X, y: Y, z: ZI) -> Self
1728 where
1729 X: IntoIterator<Item = f64>,
1730 Y: IntoIterator<Item = f64>,
1731 ZI: IntoIterator<Item = ZJ>,
1732 ZJ: IntoIterator<Item = f64>,
1733 {
1734 let x: Vec<f64> = x.into_iter().collect();
1735 let y: Vec<f64> = y.into_iter().collect();
1736 let z: Vec<Vec<f64>> =
1737 z.into_iter()
1738 .map(|row| row.into_iter().collect())
1739 .collect();
1740 Self { x, y, z, opts: Vec::new() }
1741 }
1742
1743 pub fn new_flat<X, Y, Z>(x: X, y: Y, z: Z) -> Self
1748 where
1749 X: IntoIterator<Item = f64>,
1750 Y: IntoIterator<Item = f64>,
1751 Z: IntoIterator<Item = f64>,
1752 {
1753 let x: Vec<f64> = x.into_iter().collect();
1754 if x.is_empty() { panic!("x-coordinate array cannot be empty"); }
1755 let y: Vec<f64> = y.into_iter().collect();
1756 let z: Vec<Vec<f64>> =
1757 Chunks::new(z.into_iter(), x.len())
1758 .collect();
1759 Self { x, y, z, opts: Vec::new() }
1760 }
1761}
1762
1763pub fn contourf<X, Y, ZI, ZJ>(x: X, y: Y, z: ZI) -> Contourf
1765where
1766 X: IntoIterator<Item = f64>,
1767 Y: IntoIterator<Item = f64>,
1768 ZI: IntoIterator<Item = ZJ>,
1769 ZJ: IntoIterator<Item = f64>,
1770{
1771 Contourf::new(x, y, z)
1772}
1773
1774pub fn contourf_flat<X, Y, Z>(x: X, y: Y, z: Z) -> Contourf
1779where
1780 X: IntoIterator<Item = f64>,
1781 Y: IntoIterator<Item = f64>,
1782 Z: IntoIterator<Item = f64>,
1783{
1784 Contourf::new_flat(x, y, z)
1785}
1786
1787impl Matplotlib for Contourf {
1788 fn is_prelude(&self) -> bool { false }
1789
1790 fn data(&self) -> Option<Value> {
1791 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1792 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1793 let z: Vec<Value> =
1794 self.z.iter()
1795 .map(|row| {
1796 let row: Vec<Value> =
1797 row.iter().copied().map(Value::from).collect();
1798 Value::Array(row)
1799 })
1800 .collect();
1801 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
1802 }
1803
1804 fn py_cmd(&self) -> String {
1805 format!("im = ax.contourf(data[0], data[1], data[2]{}{})",
1806 if self.opts.is_empty() { "" } else { ", " },
1807 self.opts.as_py(),
1808 )
1809 }
1810}
1811
1812impl MatplotlibOpts for Contourf {
1813 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1814 self.opts.push((key, val).into());
1815 self
1816 }
1817}
1818
1819#[derive(Clone, Debug, PartialEq)]
1832pub struct Imshow {
1833 pub data: Vec<Vec<f64>>,
1835 pub opts: Vec<Opt>,
1837}
1838
1839impl Imshow {
1840 pub fn new<I, J>(data: I) -> Self
1842 where
1843 I: IntoIterator<Item = J>,
1844 J: IntoIterator<Item = f64>,
1845 {
1846 let data: Vec<Vec<f64>> =
1847 data.into_iter()
1848 .map(|row| row.into_iter().collect())
1849 .collect();
1850 Self { data, opts: Vec::new() }
1851 }
1852
1853 pub fn new_flat<I>(data: I, rowlen: usize) -> Self
1858 where I: IntoIterator<Item = f64>
1859 {
1860 if rowlen == 0 { panic!("row length cannot be zero"); }
1861 let data: Vec<Vec<f64>> =
1862 Chunks::new(data.into_iter(), rowlen)
1863 .collect();
1864 Self { data, opts: Vec::new() }
1865 }
1866}
1867
1868pub fn imshow<I, J>(data: I) -> Imshow
1870where
1871 I: IntoIterator<Item = J>,
1872 J: IntoIterator<Item = f64>,
1873{
1874 Imshow::new(data)
1875}
1876
1877pub fn imshow_flat<I>(data: I, rowlen: usize) -> Imshow
1882where I: IntoIterator<Item = f64>
1883{
1884 Imshow::new_flat(data, rowlen)
1885}
1886
1887impl Matplotlib for Imshow {
1888 fn is_prelude(&self) -> bool { false }
1889
1890 fn data(&self) -> Option<Value> {
1891 let data: Vec<Value> =
1892 self.data.iter()
1893 .map(|row| {
1894 let row: Vec<Value> =
1895 row.iter().copied().map(Value::from).collect();
1896 Value::Array(row)
1897 })
1898 .collect();
1899 Some(Value::Array(data))
1900 }
1901
1902 fn py_cmd(&self) -> String {
1903 format!("im = ax.imshow(data{}{})",
1904 if self.opts.is_empty() { "" } else { ", " },
1905 self.opts.as_py(),
1906 )
1907 }
1908}
1909
1910impl MatplotlibOpts for Imshow {
1911 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1912 self.opts.push((key, val).into());
1913 self
1914 }
1915}
1916
1917#[derive(Clone, Debug, PartialEq)]
1927pub struct FillBetween {
1928 pub x: Vec<f64>,
1930 pub y1: Vec<f64>,
1932 pub y2: Vec<f64>,
1934 pub opts: Vec<Opt>,
1936}
1937
1938impl FillBetween {
1939 pub fn new<X, Y1, Y2>(x: X, y1: Y1, y2: Y2) -> Self
1941 where
1942 X: IntoIterator<Item = f64>,
1943 Y1: IntoIterator<Item = f64>,
1944 Y2: IntoIterator<Item = f64>,
1945 {
1946 Self {
1947 x: x.into_iter().collect(),
1948 y1: y1.into_iter().collect(),
1949 y2: y2.into_iter().collect(),
1950 opts: Vec::new(),
1951 }
1952 }
1953
1954 pub fn new_data<I>(data: I) -> Self
1956 where I: IntoIterator<Item = (f64, f64, f64)>
1957 {
1958 let ((x, y1), y2) = data.into_iter().map(assoc).unzip();
1959 Self { x, y1, y2, opts: Vec::new() }
1960 }
1961}
1962
1963pub fn fill_between<X, Y1, Y2>(x: X, y1: Y1, y2: Y2) -> FillBetween
1965where
1966 X: IntoIterator<Item = f64>,
1967 Y1: IntoIterator<Item = f64>,
1968 Y2: IntoIterator<Item = f64>,
1969{
1970 FillBetween::new(x, y1, y2)
1971}
1972
1973pub fn fill_between_data<I>(data: I) -> FillBetween
1975where I: IntoIterator<Item = (f64, f64, f64)>
1976{
1977 FillBetween::new_data(data)
1978}
1979
1980impl Matplotlib for FillBetween {
1981 fn is_prelude(&self) -> bool { false }
1982
1983 fn data(&self) -> Option<Value> {
1984 let x: Vec<Value> =
1985 self.x.iter().copied().map(Value::from).collect();
1986 let y1: Vec<Value> =
1987 self.y1.iter().copied().map(Value::from).collect();
1988 let y2: Vec<Value> =
1989 self.y2.iter().copied().map(Value::from).collect();
1990 Some(Value::Array(vec![x.into(), y1.into(), y2.into()]))
1991 }
1992
1993 fn py_cmd(&self) -> String {
1994 format!("ax.fill_between(data[0], data[1], data[2]{}{})",
1995 if self.opts.is_empty() { "" } else { ", " },
1996 self.opts.as_py(),
1997 )
1998 }
1999}
2000
2001impl MatplotlibOpts for FillBetween {
2002 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2003 self.opts.push((key, val).into());
2004 self
2005 }
2006}
2007
2008impl From<Errorbar> for FillBetween {
2010 fn from(errorbar: Errorbar) -> Self {
2011 let Errorbar { x, mut y, mut e, opts } = errorbar;
2012 y.iter_mut()
2013 .zip(e.iter_mut())
2014 .for_each(|(yk, ek)| {
2015 let y = *yk;
2016 let e = *ek;
2017 *yk -= e;
2018 *ek += y;
2019 });
2020 Self { x, y1: y, y2: e, opts }
2021 }
2022}
2023
2024impl From<Errorbar2> for FillBetween {
2026 fn from(errorbar2: Errorbar2) -> Self {
2027 let Errorbar2 { x, mut y, mut e_neg, e_pos, opts } = errorbar2;
2028 y.iter_mut()
2029 .zip(e_neg.iter_mut().zip(e_pos.iter()))
2030 .for_each(|(yk, (emk, epk))| {
2031 let y = *yk;
2032 let em = *emk;
2033 let ep = *epk;
2034 *yk -= em;
2035 *emk = y + ep;
2036 });
2037 Self { x, y1: y, y2: e_neg, opts }
2038 }
2039}
2040
2041#[derive(Clone, Debug, PartialEq)]
2051pub struct FillBetweenX {
2052 pub y: Vec<f64>,
2054 pub x1: Vec<f64>,
2056 pub x2: Vec<f64>,
2058 pub opts: Vec<Opt>,
2060}
2061
2062impl FillBetweenX {
2063 pub fn new<Y, X1, X2>(y: Y, x1: X1, x2: X2) -> Self
2065 where
2066 Y: IntoIterator<Item = f64>,
2067 X1: IntoIterator<Item = f64>,
2068 X2: IntoIterator<Item = f64>,
2069 {
2070 Self {
2071 y: y.into_iter().collect(),
2072 x1: x1.into_iter().collect(),
2073 x2: x2.into_iter().collect(),
2074 opts: Vec::new(),
2075 }
2076 }
2077
2078 pub fn new_data<I>(data: I) -> Self
2080 where I: IntoIterator<Item = (f64, f64, f64)>
2081 {
2082 let ((y, x1), x2) = data.into_iter().map(assoc).unzip();
2083 Self { y, x1, x2, opts: Vec::new() }
2084 }
2085}
2086
2087pub fn fill_betweenx<Y, X1, X2>(y: Y, x1: X1, x2: X2) -> FillBetweenX
2089where
2090 Y: IntoIterator<Item = f64>,
2091 X1: IntoIterator<Item = f64>,
2092 X2: IntoIterator<Item = f64>,
2093{
2094 FillBetweenX::new(y, x1, x2)
2095}
2096
2097pub fn fill_betweenx_data<I>(data: I) -> FillBetweenX
2099where I: IntoIterator<Item = (f64, f64, f64)>
2100{
2101 FillBetweenX::new_data(data)
2102}
2103
2104impl Matplotlib for FillBetweenX {
2105 fn is_prelude(&self) -> bool { false }
2106
2107 fn data(&self) -> Option<Value> {
2108 let y: Vec<Value> =
2109 self.y.iter().copied().map(Value::from).collect();
2110 let x1: Vec<Value> =
2111 self.x1.iter().copied().map(Value::from).collect();
2112 let x2: Vec<Value> =
2113 self.x2.iter().copied().map(Value::from).collect();
2114 Some(Value::Array(vec![y.into(), x1.into(), x2.into()]))
2115 }
2116
2117 fn py_cmd(&self) -> String {
2118 format!("ax.fill_betweenx(data[0], data[1], data[2]{}{})",
2119 if self.opts.is_empty() { "" } else { ", " },
2120 self.opts.as_py(),
2121 )
2122 }
2123}
2124
2125impl MatplotlibOpts for FillBetweenX {
2126 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2127 self.opts.push((key, val).into());
2128 self
2129 }
2130}
2131
2132#[derive(Clone, Debug, PartialEq)]
2142pub struct AxHLine {
2143 pub y: f64,
2145 pub opts: Vec<Opt>,
2147}
2148
2149impl AxHLine {
2150 pub fn new(y: f64) -> Self {
2152 Self { y, opts: Vec::new() }
2153 }
2154}
2155
2156pub fn axhline(y: f64) -> AxHLine { AxHLine::new(y) }
2158
2159impl Matplotlib for AxHLine {
2160 fn is_prelude(&self) -> bool { false }
2161
2162 fn data(&self) -> Option<Value> { None }
2163
2164 fn py_cmd(&self) -> String {
2165 format!("ax.axhline({}{}{})",
2166 self.y,
2167 if self.opts.is_empty() { "" } else { ", " },
2168 self.opts.as_py(),
2169 )
2170 }
2171}
2172
2173impl MatplotlibOpts for AxHLine {
2174 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2175 self.opts.push((key, val).into());
2176 self
2177 }
2178}
2179
2180#[derive(Clone, Debug, PartialEq)]
2190pub struct AxVLine {
2191 pub x: f64,
2193 pub opts: Vec<Opt>,
2195}
2196
2197impl AxVLine {
2198 pub fn new(x: f64) -> Self {
2200 Self { x, opts: Vec::new() }
2201 }
2202}
2203
2204pub fn axvline(x: f64) -> AxVLine { AxVLine::new(x) }
2206
2207impl Matplotlib for AxVLine {
2208 fn is_prelude(&self) -> bool { false }
2209
2210 fn data(&self) -> Option<Value> { None }
2211
2212 fn py_cmd(&self) -> String {
2213 format!("ax.axvline({}{}{})",
2214 self.x,
2215 if self.opts.is_empty() { "" } else { ", " },
2216 self.opts.as_py(),
2217 )
2218 }
2219}
2220
2221impl MatplotlibOpts for AxVLine {
2222 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2223 self.opts.push((key, val).into());
2224 self
2225 }
2226}
2227
2228#[derive(Clone, Debug, PartialEq)]
2234pub struct AxLine {
2235 pub xy1: (f64, f64),
2237 pub xy2: (f64, f64),
2239 pub opts: Vec<Opt>,
2241}
2242
2243impl AxLine {
2244 pub fn new(xy1: (f64, f64), xy2: (f64, f64)) -> Self {
2246 Self { xy1, xy2, opts: Vec::new() }
2247 }
2248}
2249
2250pub fn axline(xy1: (f64, f64), xy2: (f64, f64)) -> AxLine {
2252 AxLine::new(xy1, xy2)
2253}
2254
2255impl Matplotlib for AxLine {
2256 fn is_prelude(&self) -> bool { false }
2257
2258 fn data(&self) -> Option<Value> { None }
2259
2260 fn py_cmd(&self) -> String {
2261 format!("ax.axline({:?}, {:?}{}{})",
2262 self.xy1,
2263 self.xy2,
2264 if self.opts.is_empty() { "" } else { ", " },
2265 self.opts.as_py(),
2266 )
2267 }
2268}
2269
2270impl MatplotlibOpts for AxLine {
2271 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2272 self.opts.push((key, val).into());
2273 self
2274 }
2275}
2276
2277#[derive(Clone, Debug, PartialEq)]
2283pub struct AxLineM {
2284 pub xy: (f64, f64),
2286 pub m: f64,
2288 pub opts: Vec<Opt>,
2290}
2291
2292impl AxLineM {
2293 pub fn new(xy: (f64, f64), m: f64) -> Self {
2295 Self { xy, m, opts: Vec::new() }
2296 }
2297}
2298
2299pub fn axlinem(xy: (f64, f64), m: f64) -> AxLineM { AxLineM::new(xy, m) }
2301
2302impl Matplotlib for AxLineM {
2303 fn is_prelude(&self) -> bool { false }
2304
2305 fn data(&self) -> Option<Value> { None }
2306
2307 fn py_cmd(&self) -> String {
2308 format!("ax.axline({:?}, xy2=None, slope={}{}{})",
2309 self.xy,
2310 self.m,
2311 if self.opts.is_empty() { "" } else { ", " },
2312 self.opts.as_py(),
2313 )
2314 }
2315}
2316
2317impl MatplotlibOpts for AxLineM {
2318 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2319 self.opts.push((key, val).into());
2320 self
2321 }
2322}
2323
2324#[derive(Clone, Debug, PartialEq)]
2334pub struct Pie {
2335 pub data: Vec<f64>,
2337 pub opts: Vec<Opt>,
2339}
2340
2341impl Pie {
2342 pub fn new<I>(data: I) -> Self
2344 where I: IntoIterator<Item = f64>
2345 {
2346 Self { data: data.into_iter().collect(), opts: Vec::new() }
2347 }
2348}
2349
2350pub fn pie<I>(data: I) -> Pie
2352where I: IntoIterator<Item = f64>
2353{
2354 Pie::new(data)
2355}
2356
2357impl Matplotlib for Pie {
2358 fn is_prelude(&self) -> bool { false }
2359
2360 fn data(&self) -> Option<Value> {
2361 Some(Value::Array(
2362 self.data.iter().copied().map(Value::from).collect()))
2363 }
2364
2365 fn py_cmd(&self) -> String {
2366 format!("ax.pie(data{}{})",
2367 if self.opts.is_empty() { "" } else { ", " },
2368 self.opts.as_py(),
2369 )
2370 }
2371}
2372
2373impl MatplotlibOpts for Pie {
2374 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2375 self.opts.push((key, val).into());
2376 self
2377 }
2378}
2379
2380#[derive(Clone, Debug, PartialEq)]
2392pub struct Text {
2393 pub x: f64,
2395 pub y: f64,
2397 pub s: String,
2399 pub opts: Vec<Opt>,
2401}
2402
2403impl Text {
2404 pub fn new(x: f64, y: f64, s: &str) -> Self {
2406 Self { x, y, s: s.into(), opts: Vec::new() }
2407 }
2408}
2409
2410pub fn text(x: f64, y: f64, s: &str) -> Text { Text::new(x, y, s) }
2412
2413impl Matplotlib for Text {
2414 fn is_prelude(&self) -> bool { false }
2415
2416 fn data(&self) -> Option<Value> {
2417 Some(Value::Array(
2418 vec![self.x.into(), self.y.into(), (&*self.s).into()]))
2419 }
2420
2421 fn py_cmd(&self) -> String {
2422 format!("ax.text(data[0], data[1], data[2]{}{})",
2423 if self.opts.is_empty() { "" } else { ", " },
2424 self.opts.as_py(),
2425 )
2426 }
2427}
2428
2429impl MatplotlibOpts for Text {
2430 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2431 self.opts.push((key, val).into());
2432 self
2433 }
2434}
2435
2436#[derive(Clone, Debug, PartialEq)]
2446pub struct AxText {
2447 pub x: f64,
2449 pub y: f64,
2451 pub s: String,
2453 pub opts: Vec<Opt>,
2455}
2456
2457impl AxText {
2458 pub fn new(x: f64, y: f64, s: &str) -> Self {
2460 Self { x, y, s: s.into(), opts: Vec::new() }
2461 }
2462}
2463
2464pub fn axtext(x: f64, y: f64, s: &str) -> AxText { AxText::new(x, y, s) }
2466
2467impl Matplotlib for AxText {
2468 fn is_prelude(&self) -> bool { false }
2469
2470 fn data(&self) -> Option<Value> {
2471 Some(Value::Array(
2472 vec![self.x.into(), self.y.into(), (&*self.s).into()]))
2473 }
2474
2475 fn py_cmd(&self) -> String {
2476 format!(
2477 "ax.text(data[0], data[1], data[2], transform=ax.transAxes{}{})",
2478 if self.opts.is_empty() { "" } else { ", " },
2479 self.opts.as_py(),
2480 )
2481 }
2482}
2483
2484impl MatplotlibOpts for AxText {
2485 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2486 self.opts.push((key, val).into());
2487 self
2488 }
2489}
2490
2491#[derive(Clone, Debug, PartialEq)]
2504pub struct FigText {
2505 pub x: f64,
2507 pub y: f64,
2509 pub s: String,
2511 pub opts: Vec<Opt>,
2513}
2514
2515impl FigText {
2516 pub fn new(x: f64, y: f64, s: &str) -> Self {
2518 Self { x, y, s: s.into(), opts: Vec::new() }
2519 }
2520}
2521
2522pub fn figtext(x: f64, y: f64, s: &str) -> FigText { FigText::new(x, y, s) }
2524
2525impl Matplotlib for FigText {
2526 fn is_prelude(&self) -> bool { false }
2527
2528 fn data(&self) -> Option<Value> {
2529 Some(Value::Array(
2530 vec![self.x.into(), self.y.into(), (&*self.s).into()]))
2531 }
2532
2533 fn py_cmd(&self) -> String {
2534 format!(
2535 "fig.text(data[0], data[1], data[2]{}{})",
2536 if self.opts.is_empty() { "" } else { ", " },
2537 self.opts.as_py(),
2538 )
2539 }
2540}
2541
2542impl MatplotlibOpts for FigText {
2543 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2544 self.opts.push((key, val).into());
2545 self
2546 }
2547}
2548
2549#[derive(Clone, Debug, PartialEq)]
2564pub struct Colorbar {
2565 pub opts: Vec<Opt>,
2567}
2568
2569impl Default for Colorbar {
2570 fn default() -> Self { Self::new() }
2571}
2572
2573impl Colorbar {
2574 pub fn new() -> Self { Self { opts: Vec::new() } }
2576}
2577
2578pub fn colorbar() -> Colorbar { Colorbar::new() }
2580
2581impl Matplotlib for Colorbar {
2582 fn is_prelude(&self) -> bool { false }
2583
2584 fn data(&self) -> Option<Value> { None }
2585
2586 fn py_cmd(&self) -> String {
2587 format!("cbar = fig.colorbar(im, ax=ax{}{})",
2588 if self.opts.is_empty() { "" } else { ", " },
2589 self.opts.as_py(),
2590 )
2591 }
2592}
2593
2594impl MatplotlibOpts for Colorbar {
2595 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2596 self.opts.push((key, val).into());
2597 self
2598 }
2599}
2600
2601#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2611pub struct Scale {
2612 pub axis: Axis,
2614 pub scale: AxisScale,
2616}
2617
2618impl Scale {
2619 pub fn new(axis: Axis, scale: AxisScale) -> Self { Self { axis, scale } }
2621}
2622
2623pub fn scale(axis: Axis, scale: AxisScale) -> Scale { Scale::new(axis, scale) }
2625
2626pub fn xscale(scale: AxisScale) -> Scale { Scale::new(Axis::X, scale) }
2628
2629pub fn yscale(scale: AxisScale) -> Scale { Scale::new(Axis::Y, scale) }
2631
2632pub fn zscale(scale: AxisScale) -> Scale { Scale::new(Axis::Z, scale) }
2634
2635impl Matplotlib for Scale {
2636 fn is_prelude(&self) -> bool { false }
2637
2638 fn data(&self) -> Option<Value> { None }
2639
2640 fn py_cmd(&self) -> String {
2641 let ax = format!("{:?}", self.axis).to_lowercase();
2642 let sc = format!("{:?}", self.scale).to_lowercase();
2643 format!("ax.set_{}scale(\"{}\")", ax, sc)
2644 }
2645}
2646
2647#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2649pub enum Axis {
2650 X,
2652 Y,
2654 Z,
2656}
2657
2658#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2660pub enum AxisScale {
2661 Linear,
2663 Log,
2665 SymLog,
2669 Logit,
2677}
2678
2679#[derive(Copy, Clone, Debug, PartialEq)]
2689pub struct Lim {
2690 pub axis: Axis,
2692 pub min: Option<f64>,
2696 pub max: Option<f64>,
2700}
2701
2702impl Lim {
2703 pub fn new(axis: Axis, min: Option<f64>, max: Option<f64>) -> Self {
2705 Self { axis, min, max }
2706 }
2707}
2708
2709pub fn lim(axis: Axis, min: Option<f64>, max: Option<f64>) -> Lim {
2711 Lim::new(axis, min, max)
2712}
2713
2714pub fn xlim(min: Option<f64>, max: Option<f64>) -> Lim {
2716 Lim::new(Axis::X, min, max)
2717}
2718
2719pub fn ylim(min: Option<f64>, max: Option<f64>) -> Lim {
2721 Lim::new(Axis::Y, min, max)
2722}
2723
2724pub fn zlim(min: Option<f64>, max: Option<f64>) -> Lim {
2726 Lim::new(Axis::Z, min, max)
2727}
2728
2729impl Matplotlib for Lim {
2730 fn is_prelude(&self) -> bool { false }
2731
2732 fn data(&self) -> Option<Value> { None }
2733
2734 fn py_cmd(&self) -> String {
2735 let ax = format!("{:?}", self.axis).to_lowercase();
2736 let min =
2737 self.min.as_ref()
2738 .map(|x| format!("{}", x))
2739 .unwrap_or("None".into());
2740 let max =
2741 self.max.as_ref()
2742 .map(|x| format!("{}", x))
2743 .unwrap_or("None".into());
2744 format!("ax.set_{}lim({}, {})", ax, min, max)
2745 }
2746}
2747
2748#[derive(Copy, Clone, Debug, PartialEq)]
2760pub struct CLim {
2761 pub min: Option<f64>,
2765 pub max: Option<f64>,
2769}
2770
2771impl CLim {
2772 pub fn new(min: Option<f64>, max: Option<f64>) -> Self {
2774 Self { min, max }
2775 }
2776}
2777
2778pub fn clim(min: Option<f64>, max: Option<f64>) -> CLim { CLim::new(min, max) }
2780
2781impl Matplotlib for CLim {
2782 fn is_prelude(&self) -> bool { false }
2783
2784 fn data(&self) -> Option<Value> { None }
2785
2786 fn py_cmd(&self) -> String {
2787 let min =
2788 self.min.as_ref()
2789 .map(|x| format!("{}", x))
2790 .unwrap_or("None".into());
2791 let max =
2792 self.max.as_ref()
2793 .map(|x| format!("{}", x))
2794 .unwrap_or("None".into());
2795 format!("im.set_clim({}, {})", min, max)
2796 }
2797}
2798
2799#[derive(Clone, Debug, PartialEq)]
2809pub struct Title {
2810 pub s: String,
2812 pub opts: Vec<Opt>,
2814}
2815
2816impl Title {
2817 pub fn new(s: &str) -> Self {
2819 Self { s: s.into(), opts: Vec::new() }
2820 }
2821}
2822
2823pub fn title(s: &str) -> Title { Title::new(s) }
2825
2826impl Matplotlib for Title {
2827 fn is_prelude(&self) -> bool { false }
2828
2829 fn data(&self) -> Option<Value> { None }
2830
2831 fn py_cmd(&self) -> String {
2832 format!("ax.set_title(\"{}\"{}{})",
2833 self.s,
2834 if self.opts.is_empty() { "" } else { ", " },
2835 self.opts.as_py(),
2836 )
2837 }
2838}
2839
2840impl MatplotlibOpts for Title {
2841 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2842 self.opts.push((key, val).into());
2843 self
2844 }
2845}
2846
2847#[derive(Clone, Debug, PartialEq)]
2857pub struct Label {
2858 pub axis: Axis,
2860 pub s: String,
2862 pub opts: Vec<Opt>,
2864}
2865
2866impl Label {
2867 pub fn new(axis: Axis, s: &str) -> Self {
2869 Self { axis, s: s.into(), opts: Vec::new() }
2870 }
2871}
2872
2873pub fn label(axis: Axis, s: &str) -> Label { Label::new(axis, s) }
2875
2876pub fn xlabel(s: &str) -> Label { Label::new(Axis::X, s) }
2878
2879pub fn ylabel(s: &str) -> Label { Label::new(Axis::Y, s) }
2881
2882pub fn zlabel(s: &str) -> Label { Label::new(Axis::Z, s) }
2884
2885impl Matplotlib for Label {
2886 fn is_prelude(&self) -> bool { false }
2887
2888 fn data(&self) -> Option<Value> { None }
2889
2890 fn py_cmd(&self) -> String {
2891 let ax = format!("{:?}", self.axis).to_lowercase();
2892 format!("ax.set_{}label(\"{}\"{}{})",
2893 ax,
2894 self.s,
2895 if self.opts.is_empty() { "" } else { ", " },
2896 self.opts.as_py(),
2897 )
2898 }
2899}
2900
2901impl MatplotlibOpts for Label {
2902 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2903 self.opts.push((key, val).into());
2904 self
2905 }
2906}
2907
2908#[derive(Clone, Debug, PartialEq)]
2921pub struct CLabel {
2922 pub s: String,
2924 pub opts: Vec<Opt>,
2926}
2927
2928impl CLabel {
2929 pub fn new(s: &str) -> Self {
2931 Self { s: s.into(), opts: Vec::new() }
2932 }
2933}
2934
2935pub fn clabel(s: &str) -> CLabel { CLabel::new(s) }
2937
2938impl Matplotlib for CLabel {
2939 fn is_prelude(&self) -> bool { false }
2940
2941 fn data(&self) -> Option<Value> { None }
2942
2943 fn py_cmd(&self) -> String {
2944 format!("cbar.set_label(\"{}\"{}{})",
2945 self.s,
2946 if self.opts.is_empty() { "" } else { ", " },
2947 self.opts.as_py(),
2948 )
2949 }
2950}
2951
2952impl MatplotlibOpts for CLabel {
2953 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2954 self.opts.push((key, val).into());
2955 self
2956 }
2957}
2958
2959#[derive(Clone, Debug, PartialEq)]
2969pub struct Ticks {
2970 pub axis: Axis,
2972 pub v: Vec<f64>,
2974 pub opts: Vec<Opt>,
2976}
2977
2978impl Ticks {
2979 pub fn new<I>(axis: Axis, v: I) -> Self
2981 where I: IntoIterator<Item = f64>
2982 {
2983 Self { axis, v: v.into_iter().collect(), opts: Vec::new() }
2984 }
2985}
2986
2987pub fn ticks<I>(axis: Axis, v: I) -> Ticks
2989where I: IntoIterator<Item = f64>
2990{
2991 Ticks::new(axis, v)
2992}
2993
2994pub fn xticks<I>(v: I) -> Ticks
2996where I: IntoIterator<Item = f64>
2997{
2998 Ticks::new(Axis::X, v)
2999}
3000
3001pub fn yticks<I>(v: I) -> Ticks
3003where I: IntoIterator<Item = f64>
3004{
3005 Ticks::new(Axis::Y, v)
3006}
3007
3008pub fn zticks<I>(v: I) -> Ticks
3010where I: IntoIterator<Item = f64>
3011{
3012 Ticks::new(Axis::Z, v)
3013}
3014
3015impl Matplotlib for Ticks {
3016 fn is_prelude(&self) -> bool { false }
3017
3018 fn data(&self) -> Option<Value> {
3019 let v: Vec<Value> = self.v.iter().copied().map(Value::from).collect();
3020 Some(Value::Array(v))
3021 }
3022
3023 fn py_cmd(&self) -> String {
3024 format!("ax.set_{}ticks(data{}{})",
3025 format!("{:?}", self.axis).to_lowercase(),
3026 if self.opts.is_empty() { "" } else { ", " },
3027 self.opts.as_py(),
3028 )
3029 }
3030}
3031
3032impl MatplotlibOpts for Ticks {
3033 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3034 self.opts.push((key, val).into());
3035 self
3036 }
3037}
3038
3039#[derive(Clone, Debug, PartialEq)]
3052pub struct CTicks {
3053 pub v: Vec<f64>,
3055 pub opts: Vec<Opt>,
3057}
3058
3059impl CTicks {
3060 pub fn new<I>(v: I) -> Self
3062 where I: IntoIterator<Item = f64>
3063 {
3064 Self { v: v.into_iter().collect(), opts: Vec::new() }
3065 }
3066}
3067
3068pub fn cticks<I>(v: I) -> CTicks
3070where I: IntoIterator<Item = f64>
3071{
3072 CTicks::new(v)
3073}
3074
3075impl Matplotlib for CTicks {
3076 fn is_prelude(&self) -> bool { false }
3077
3078 fn data(&self) -> Option<Value> {
3079 let v: Vec<Value> =
3080 self.v.iter().copied().map(Value::from).collect();
3081 Some(Value::Array(v))
3082 }
3083
3084 fn py_cmd(&self) -> String {
3085 format!("cbar.set_ticks(data{}{})",
3086 if self.opts.is_empty() { "" } else { ", " },
3087 self.opts.as_py(),
3088 )
3089 }
3090}
3091
3092impl MatplotlibOpts for CTicks {
3093 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3094 self.opts.push((key, val).into());
3095 self
3096 }
3097}
3098
3099#[derive(Clone, Debug, PartialEq)]
3109pub struct TickLabels {
3110 pub axis: Axis,
3112 pub v: Vec<f64>,
3114 pub s: Vec<String>,
3116 pub opts: Vec<Opt>,
3118}
3119
3120impl TickLabels {
3121 pub fn new<I, J, S>(axis: Axis, v: I, s: J) -> Self
3123 where
3124 I: IntoIterator<Item = f64>,
3125 J: IntoIterator<Item = S>,
3126 S: Into<String>,
3127 {
3128 Self {
3129 axis,
3130 v: v.into_iter().collect(),
3131 s: s.into_iter().map(|sk| sk.into()).collect(),
3132 opts: Vec::new(),
3133 }
3134 }
3135
3136 pub fn new_data<I, S>(axis: Axis, ticklabels: I) -> Self
3138 where
3139 I: IntoIterator<Item = (f64, S)>,
3140 S: Into<String>,
3141 {
3142 let (v, s): (Vec<f64>, Vec<String>) =
3143 ticklabels.into_iter()
3144 .map(|(vk, sk)| (vk, sk.into()))
3145 .unzip();
3146 Self { axis, v, s, opts: Vec::new() }
3147 }
3148}
3149
3150pub fn ticklabels<I, J, S>(axis: Axis, v: I, s: J) -> TickLabels
3152where
3153 I: IntoIterator<Item = f64>,
3154 J: IntoIterator<Item = S>,
3155 S: Into<String>,
3156{
3157 TickLabels::new(axis, v, s)
3158}
3159
3160pub fn ticklabels_data<I, S>(axis: Axis, ticklabels: I) -> TickLabels
3162where
3163 I: IntoIterator<Item = (f64, S)>,
3164 S: Into<String>,
3165{
3166 TickLabels::new_data(axis, ticklabels)
3167}
3168
3169pub fn xticklabels<I, J, S>(v: I, s: J) -> TickLabels
3171where
3172 I: IntoIterator<Item = f64>,
3173 J: IntoIterator<Item = S>,
3174 S: Into<String>,
3175{
3176 TickLabels::new(Axis::X, v, s)
3177}
3178
3179pub fn xticklabels_data<I, S>(ticklabels: I) -> TickLabels
3182where
3183 I: IntoIterator<Item = (f64, S)>,
3184 S: Into<String>,
3185{
3186 TickLabels::new_data(Axis::X, ticklabels)
3187}
3188
3189pub fn yticklabels<I, J, S>(v: I, s: J) -> TickLabels
3191where
3192 I: IntoIterator<Item = f64>,
3193 J: IntoIterator<Item = S>,
3194 S: Into<String>,
3195{
3196 TickLabels::new(Axis::Y, v, s)
3197}
3198
3199pub fn yticklabels_data<I, S>(ticklabels: I) -> TickLabels
3202where
3203 I: IntoIterator<Item = (f64, S)>,
3204 S: Into<String>,
3205{
3206 TickLabels::new_data(Axis::Y, ticklabels)
3207}
3208
3209pub fn zticklabels<I, J, S>(v: I, s: J) -> TickLabels
3211where
3212 I: IntoIterator<Item = f64>,
3213 J: IntoIterator<Item = S>,
3214 S: Into<String>,
3215{
3216 TickLabels::new(Axis::Z, v, s)
3217}
3218
3219pub fn zticklabels_data<I, S>(ticklabels: I) -> TickLabels
3222where
3223 I: IntoIterator<Item = (f64, S)>,
3224 S: Into<String>,
3225{
3226 TickLabels::new_data(Axis::Z, ticklabels)
3227}
3228
3229impl Matplotlib for TickLabels {
3230 fn is_prelude(&self) -> bool { false }
3231
3232 fn data(&self) -> Option<Value> {
3233 let v: Vec<Value> = self.v.iter().copied().map(Value::from).collect();
3234 let s: Vec<Value> = self.s.iter().cloned().map(Value::from).collect();
3235 Some(Value::Array(vec![v.into(), s.into()]))
3236 }
3237
3238 fn py_cmd(&self) -> String {
3239 format!("ax.set_{}ticks(data[0], labels=data[1]{}{})",
3240 format!("{:?}", self.axis).to_lowercase(),
3241 if self.opts.is_empty() { "" } else { ", " },
3242 self.opts.as_py(),
3243 )
3244 }
3245}
3246
3247impl MatplotlibOpts for TickLabels {
3248 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3249 self.opts.push((key, val).into());
3250 self
3251 }
3252}
3253
3254#[derive(Clone, Debug, PartialEq)]
3267pub struct CTickLabels {
3268 pub v: Vec<f64>,
3270 pub s: Vec<String>,
3272 pub opts: Vec<Opt>,
3274}
3275
3276impl CTickLabels {
3277 pub fn new<I, J, S>(v: I, s: J) -> Self
3279 where
3280 I: IntoIterator<Item = f64>,
3281 J: IntoIterator<Item = S>,
3282 S: Into<String>,
3283 {
3284 Self {
3285 v: v.into_iter().collect(),
3286 s: s.into_iter().map(|sk| sk.into()).collect(),
3287 opts: Vec::new(),
3288 }
3289 }
3290
3291 pub fn new_data<I, S>(ticklabels: I) -> Self
3293 where
3294 I: IntoIterator<Item = (f64, S)>,
3295 S: Into<String>,
3296 {
3297 let (v, s): (Vec<f64>, Vec<String>) =
3298 ticklabels.into_iter()
3299 .map(|(vk, sk)| (vk, sk.into()))
3300 .unzip();
3301 Self { v, s, opts: Vec::new() }
3302 }
3303}
3304
3305pub fn cticklabels<I, J, S>(v: I, s: J) -> CTickLabels
3307where
3308 I: IntoIterator<Item = f64>,
3309 J: IntoIterator<Item = S>,
3310 S: Into<String>,
3311{
3312 CTickLabels::new(v, s)
3313}
3314
3315pub fn cticklabels_data<I, S>(ticklabels: I) -> CTickLabels
3317where
3318 I: IntoIterator<Item = (f64, S)>,
3319 S: Into<String>,
3320{
3321 CTickLabels::new_data(ticklabels)
3322}
3323
3324impl Matplotlib for CTickLabels {
3325 fn is_prelude(&self) -> bool { false }
3326
3327 fn data(&self) -> Option<Value> {
3328 let v: Vec<Value> =
3329 self.v.iter().copied().map(Value::from).collect();
3330 let s: Vec<Value> =
3331 self.s.iter().cloned().map(Value::from).collect();
3332 Some(Value::Array(vec![v.into(), s.into()]))
3333 }
3334
3335 fn py_cmd(&self) -> String {
3336 format!("cbar.set_ticks(data[0], labels=data[1]{}{})",
3337 if self.opts.is_empty() { "" } else { ", " },
3338 self.opts.as_py(),
3339 )
3340 }
3341}
3342
3343impl MatplotlibOpts for CTickLabels {
3344 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3345 self.opts.push((key, val).into());
3346 self
3347 }
3348}
3349
3350#[derive(Clone, Debug, PartialEq)]
3360pub struct TickParams {
3361 pub axis: Axis2,
3363 pub opts: Vec<Opt>,
3365}
3366
3367impl TickParams {
3368 pub fn new(axis: Axis2) -> Self {
3370 Self { axis, opts: Vec::new() }
3371 }
3372}
3373
3374pub fn tick_params(axis: Axis2) -> TickParams { TickParams::new(axis) }
3376
3377pub fn xtick_params() -> TickParams { TickParams::new(Axis2::X) }
3379
3380pub fn ytick_params() -> TickParams { TickParams::new(Axis2::Y) }
3382
3383impl Matplotlib for TickParams {
3384 fn is_prelude(&self) -> bool { false }
3385
3386 fn data(&self) -> Option<Value> { None }
3387
3388 fn py_cmd(&self) -> String {
3389 format!("ax.tick_params(\"{}\"{}{})",
3390 format!("{:?}", self.axis).to_lowercase(),
3391 if self.opts.is_empty() { "" } else { ", " },
3392 self.opts.as_py(),
3393 )
3394 }
3395}
3396
3397impl MatplotlibOpts for TickParams {
3398 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3399 self.opts.push((key, val).into());
3400 self
3401 }
3402}
3403
3404#[derive(Copy, Clone, Debug, PartialEq, Eq)]
3406pub enum Axis2 {
3407 X,
3409 Y,
3411 Both,
3413}
3414
3415#[derive(Clone, Debug, PartialEq)]
3425pub struct SupTitle {
3426 pub s: String,
3428 pub opts: Vec<Opt>,
3430}
3431
3432impl SupTitle {
3433 pub fn new(s: &str) -> Self {
3435 Self { s: s.into(), opts: Vec::new() }
3436 }
3437}
3438
3439pub fn suptitle(s: &str) -> SupTitle { SupTitle::new(s) }
3441
3442impl Matplotlib for SupTitle {
3443 fn is_prelude(&self) -> bool { false }
3444
3445 fn data(&self) -> Option<Value> { None }
3446
3447 fn py_cmd(&self) -> String {
3448 format!("fig.suptitle(\"{}\"{}{})",
3449 self.s,
3450 if self.opts.is_empty() { "" } else { ", " },
3451 self.opts.as_py(),
3452 )
3453 }
3454}
3455
3456impl MatplotlibOpts for SupTitle {
3457 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3458 self.opts.push((key, val).into());
3459 self
3460 }
3461}
3462
3463#[derive(Clone, Debug, PartialEq)]
3473pub struct SupXLabel {
3474 pub s: String,
3476 pub opts: Vec<Opt>,
3478}
3479
3480impl SupXLabel {
3481 pub fn new(s: &str) -> Self {
3483 Self { s: s.into(), opts: Vec::new() }
3484 }
3485}
3486
3487pub fn supxlabel(s: &str) -> SupXLabel { SupXLabel::new(s) }
3489
3490impl Matplotlib for SupXLabel {
3491 fn is_prelude(&self) -> bool { false }
3492
3493 fn data(&self) -> Option<Value> { None }
3494
3495 fn py_cmd(&self) -> String {
3496 format!("fig.supxlabel(\"{}\"{}{})",
3497 self.s,
3498 if self.opts.is_empty() { "" } else { ", " },
3499 self.opts.as_py(),
3500 )
3501 }
3502}
3503
3504impl MatplotlibOpts for SupXLabel {
3505 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3506 self.opts.push((key, val).into());
3507 self
3508 }
3509}
3510
3511#[derive(Clone, Debug, PartialEq)]
3521pub struct SupYLabel {
3522 pub s: String,
3524 pub opts: Vec<Opt>,
3526}
3527
3528impl SupYLabel {
3529 pub fn new(s: &str) -> Self {
3531 Self { s: s.into(), opts: Vec::new() }
3532 }
3533}
3534
3535pub fn supylabel(s: &str) -> SupYLabel { SupYLabel::new(s) }
3537
3538impl Matplotlib for SupYLabel {
3539 fn is_prelude(&self) -> bool { false }
3540
3541 fn data(&self) -> Option<Value> { None }
3542
3543 fn py_cmd(&self) -> String {
3544 format!("fig.supylabel(\"{}\"{}{})",
3545 self.s,
3546 if self.opts.is_empty() { "" } else { ", " },
3547 self.opts.as_py(),
3548 )
3549 }
3550}
3551
3552impl MatplotlibOpts for SupYLabel {
3553 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3554 self.opts.push((key, val).into());
3555 self
3556 }
3557}
3558
3559#[derive(Clone, Debug, PartialEq)]
3569pub struct Legend {
3570 pub opts: Vec<Opt>,
3572}
3573
3574impl Default for Legend {
3575 fn default() -> Self { Self::new() }
3576}
3577
3578impl Legend {
3579 pub fn new() -> Self {
3581 Self { opts: Vec::new() }
3582 }
3583}
3584
3585pub fn legend() -> Legend { Legend::new() }
3587
3588impl Matplotlib for Legend {
3589 fn is_prelude(&self) -> bool { false }
3590
3591 fn data(&self) -> Option<Value> { None }
3592
3593 fn py_cmd(&self) -> String {
3594 format!("ax.legend({})", self.opts.as_py())
3595 }
3596}
3597
3598impl MatplotlibOpts for Legend {
3599 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3600 self.opts.push((key, val).into());
3601 self
3602 }
3603}
3604
3605#[derive(Clone, Debug, PartialEq)]
3615pub struct Grid {
3616 pub onoff: bool,
3618 pub opts: Vec<Opt>,
3620}
3621
3622impl Grid {
3623 pub fn new(onoff: bool) -> Self { Self { onoff, opts: Vec::new() } }
3625}
3626
3627pub fn grid(onoff: bool) -> Grid { Grid::new(onoff) }
3629
3630impl Matplotlib for Grid {
3631 fn is_prelude(&self) -> bool { false }
3632
3633 fn data(&self) -> Option<Value> { None }
3634
3635 fn py_cmd(&self) -> String {
3636 format!("ax.grid({}, {})", self.onoff.as_py(), self.opts.as_py())
3637 }
3638}
3639
3640impl MatplotlibOpts for Grid {
3641 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3642 self.opts.push((key, val).into());
3643 self
3644 }
3645}
3646
3647#[derive(Clone, Debug, PartialEq)]
3657pub struct TightLayout {
3658 pub opts: Vec<Opt>,
3660}
3661
3662impl Default for TightLayout {
3663 fn default() -> Self { Self::new() }
3664}
3665
3666impl TightLayout {
3667 pub fn new() -> Self { Self { opts: Vec::new() } }
3669}
3670
3671pub fn tight_layout() -> TightLayout { TightLayout::new() }
3673
3674impl Matplotlib for TightLayout {
3675 fn is_prelude(&self) -> bool { false }
3676
3677 fn data(&self) -> Option<Value> { None }
3678
3679 fn py_cmd(&self) -> String {
3680 format!("fig.tight_layout({})", self.opts.as_py())
3681 }
3682}
3683
3684impl MatplotlibOpts for TightLayout {
3685 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3686 self.opts.push((key, val).into());
3687 self
3688 }
3689}
3690
3691#[derive(Clone, Debug, PartialEq)]
3703pub struct InsetAxes {
3704 pub x: f64,
3706 pub y: f64,
3708 pub w: f64,
3710 pub h: f64,
3712 pub opts: Vec<Opt>,
3714}
3715
3716impl InsetAxes {
3717 pub fn new(x: f64, y: f64, w: f64, h: f64) -> Self {
3719 Self { x, y, w, h, opts: Vec::new() }
3720 }
3721
3722 pub fn new_pairs(xy: (f64, f64), wh: (f64, f64)) -> Self {
3725 Self { x: xy.0, y: xy.1, w: wh.0, h: wh.1, opts: Vec::new() }
3726 }
3727}
3728
3729pub fn inset_axes(x: f64, y: f64, w: f64, h: f64) -> InsetAxes {
3731 InsetAxes::new(x, y, w, h)
3732}
3733
3734pub fn inset_axes_pairs(xy: (f64, f64), wh: (f64, f64)) -> InsetAxes {
3737 InsetAxes::new_pairs(xy, wh)
3738}
3739
3740impl Matplotlib for InsetAxes {
3741 fn is_prelude(&self) -> bool { false }
3742
3743 fn data(&self) -> Option<Value> { None }
3744
3745 fn py_cmd(&self) -> String {
3746 format!("ax = ax.inset_axes([{}, {}, {}, {}]{}{})",
3747 self.x,
3748 self.y,
3749 self.w,
3750 self.h,
3751 if self.opts.is_empty() { "" } else { ", " },
3752 self.opts.as_py(),
3753 )
3754 }
3755}
3756
3757impl MatplotlibOpts for InsetAxes {
3758 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3759 self.opts.push((key, val).into());
3760 self
3761 }
3762}
3763
3764#[derive(Clone, Debug, PartialEq)]
3774pub struct Plot3 {
3775 pub x: Vec<f64>,
3777 pub y: Vec<f64>,
3779 pub z: Vec<f64>,
3781 pub opts: Vec<Opt>,
3783}
3784
3785impl Plot3 {
3786 pub fn new<X, Y, Z>(x: X, y: Y, z: Z) -> Self
3788 where
3789 X: IntoIterator<Item = f64>,
3790 Y: IntoIterator<Item = f64>,
3791 Z: IntoIterator<Item = f64>,
3792 {
3793 Self {
3794 x: x.into_iter().collect(),
3795 y: y.into_iter().collect(),
3796 z: z.into_iter().collect(),
3797 opts: Vec::new(),
3798 }
3799 }
3800
3801 pub fn new_data<I>(data: I) -> Self
3803 where I: IntoIterator<Item = (f64, f64, f64)>
3804 {
3805 let ((x, y), z) = data.into_iter().map(assoc).unzip();
3806 Self { x, y, z, opts: Vec::new() }
3807 }
3808}
3809
3810pub fn plot3<X, Y, Z>(x: X, y: Y, z: Z) -> Plot3
3812where
3813 X: IntoIterator<Item = f64>,
3814 Y: IntoIterator<Item = f64>,
3815 Z: IntoIterator<Item = f64>,
3816{
3817 Plot3::new(x, y, z)
3818}
3819
3820pub fn plot3_data<I>(data: I) -> Plot3
3822where I: IntoIterator<Item = (f64, f64, f64)>
3823{
3824 Plot3::new_data(data)
3825}
3826
3827impl Matplotlib for Plot3 {
3828 fn is_prelude(&self) -> bool { false }
3829
3830 fn data(&self) -> Option<Value> {
3831 let x: Vec<Value> =
3832 self.x.iter().copied().map(Value::from).collect();
3833 let y: Vec<Value> =
3834 self.y.iter().copied().map(Value::from).collect();
3835 let z: Vec<Value> =
3836 self.z.iter().copied().map(Value::from).collect();
3837 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
3838 }
3839
3840 fn py_cmd(&self) -> String {
3841 format!("ax.plot(data[0], data[1], data[2]{}{})",
3842 if self.opts.is_empty() { "" } else { ", " },
3843 self.opts.as_py(),
3844 )
3845 }
3846}
3847
3848impl MatplotlibOpts for Plot3 {
3849 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3850 self.opts.push((key, val).into());
3851 self
3852 }
3853}
3854
3855#[derive(Clone, Debug, PartialEq)]
3865pub struct Scatter3 {
3866 pub x: Vec<f64>,
3868 pub y: Vec<f64>,
3870 pub z: Vec<f64>,
3872 pub opts: Vec<Opt>,
3874}
3875
3876impl Scatter3 {
3877 pub fn new<X, Y, Z>(x: X, y: Y, z: Z) -> Self
3879 where
3880 X: IntoIterator<Item = f64>,
3881 Y: IntoIterator<Item = f64>,
3882 Z: IntoIterator<Item = f64>,
3883 {
3884 Self {
3885 x: x.into_iter().collect(),
3886 y: y.into_iter().collect(),
3887 z: z.into_iter().collect(),
3888 opts: Vec::new(),
3889 }
3890 }
3891
3892 pub fn new_data<I>(data: I) -> Self
3894 where I: IntoIterator<Item = (f64, f64, f64)>
3895 {
3896 let ((x, y), z) = data.into_iter().map(assoc).unzip();
3897 Self { x, y, z, opts: Vec::new() }
3898 }
3899}
3900
3901pub fn scatter3<X, Y, Z>(x: X, y: Y, z: Z) -> Scatter3
3903where
3904 X: IntoIterator<Item = f64>,
3905 Y: IntoIterator<Item = f64>,
3906 Z: IntoIterator<Item = f64>,
3907{
3908 Scatter3::new(x, y, z)
3909}
3910
3911pub fn scatter3_data<I>(data: I) -> Scatter3
3913where I: IntoIterator<Item = (f64, f64, f64)>
3914{
3915 Scatter3::new_data(data)
3916}
3917
3918impl Matplotlib for Scatter3 {
3919 fn is_prelude(&self) -> bool { false }
3920
3921 fn data(&self) -> Option<Value> {
3922 let x: Vec<Value> =
3923 self.x.iter().copied().map(Value::from).collect();
3924 let y: Vec<Value> =
3925 self.y.iter().copied().map(Value::from).collect();
3926 let z: Vec<Value> =
3927 self.z.iter().copied().map(Value::from).collect();
3928 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
3929 }
3930
3931 fn py_cmd(&self) -> String {
3932 format!("ax.scatter(data[0], data[1], data[2]{}{})",
3933 if self.opts.is_empty() { "" } else { ", " },
3934 self.opts.as_py(),
3935 )
3936 }
3937}
3938
3939impl MatplotlibOpts for Scatter3 {
3940 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3941 self.opts.push((key, val).into());
3942 self
3943 }
3944}
3945
3946#[derive(Clone, Debug, PartialEq)]
3956pub struct Quiver3 {
3957 pub x: Vec<f64>,
3959 pub y: Vec<f64>,
3961 pub z: Vec<f64>,
3963 pub vx: Vec<f64>,
3965 pub vy: Vec<f64>,
3967 pub vz: Vec<f64>,
3969 pub opts: Vec<Opt>,
3971}
3972
3973impl Quiver3 {
3974 pub fn new<X, Y, Z, VX, VY, VZ>(x: X, y: Y, z: Z, vx: VX, vy: VY, vz: VZ)
3976 -> Self
3977 where
3978 X: IntoIterator<Item = f64>,
3979 Y: IntoIterator<Item = f64>,
3980 Z: IntoIterator<Item = f64>,
3981 VX: IntoIterator<Item = f64>,
3982 VY: IntoIterator<Item = f64>,
3983 VZ: IntoIterator<Item = f64>,
3984 {
3985 Self {
3986 x: x.into_iter().collect(),
3987 y: y.into_iter().collect(),
3988 z: z.into_iter().collect(),
3989 vx: vx.into_iter().collect(),
3990 vy: vy.into_iter().collect(),
3991 vz: vz.into_iter().collect(),
3992 opts: Vec::new(),
3993 }
3994 }
3995
3996 pub fn new_triples<I, VI>(xyz: I, vxyz: VI) -> Self
3999 where
4000 I: IntoIterator<Item = (f64, f64, f64)>,
4001 VI: IntoIterator<Item = (f64, f64, f64)>,
4002 {
4003 let ((x, y), z) = xyz.into_iter().map(assoc).unzip();
4004 let ((vx, vy), vz) = vxyz.into_iter().map(assoc).unzip();
4005 Self { x, y, z, vx, vy, vz, opts: Vec::new() }
4006 }
4007
4008 pub fn new_data<I>(data: I) -> Self
4012 where I: IntoIterator<Item = (f64, f64, f64, f64, f64, f64)>
4013 {
4014 let (((((x, y), z), vx), vy), vz) = data.into_iter().map(assoc).unzip();
4015 Self { x, y, z, vx, vy, vz, opts: Vec::new() }
4016 }
4017}
4018
4019pub fn quiver3<X, Y, Z, VX, VY, VZ>(x: X, y: Y, z: Z, vx: VX, vy: VY, vz: VZ)
4021 -> Quiver3
4022where
4023 X: IntoIterator<Item = f64>,
4024 Y: IntoIterator<Item = f64>,
4025 Z: IntoIterator<Item = f64>,
4026 VX: IntoIterator<Item = f64>,
4027 VY: IntoIterator<Item = f64>,
4028 VZ: IntoIterator<Item = f64>,
4029{
4030 Quiver3::new(x, y, z, vx, vy, vz)
4031}
4032
4033pub fn quiver3_triples<I, VI>(xyz: I, vxyz: VI) -> Quiver3
4036where
4037 I: IntoIterator<Item = (f64, f64, f64)>,
4038 VI: IntoIterator<Item = (f64, f64, f64)>,
4039{
4040 Quiver3::new_triples(xyz, vxyz)
4041}
4042
4043pub fn quiver3_data<I>(data: I) -> Quiver3
4048where I: IntoIterator<Item = (f64, f64, f64, f64, f64, f64)>
4049{
4050 Quiver3::new_data(data)
4051}
4052
4053impl Matplotlib for Quiver3 {
4054 fn is_prelude(&self) -> bool { false }
4055
4056 fn data(&self) -> Option<Value> {
4057 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
4058 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
4059 let z: Vec<Value> = self.z.iter().copied().map(Value::from).collect();
4060 let vx: Vec<Value> = self.vx.iter().copied().map(Value::from).collect();
4061 let vy: Vec<Value> = self.vy.iter().copied().map(Value::from).collect();
4062 let vz: Vec<Value> = self.vz.iter().copied().map(Value::from).collect();
4063 Some(Value::Array(vec![
4064 x.into(), y.into(), z.into(), vx.into(), vy.into(), vz.into()]))
4065 }
4066
4067 fn py_cmd(&self) -> String {
4068 format!(
4069 "ax.quiver(\
4070 data[0], data[1], data[2], data[3], data[4], data[5]{}{})",
4071 if self.opts.is_empty() { "" } else { ", " },
4072 self.opts.as_py(),
4073 )
4074 }
4075}
4076
4077impl MatplotlibOpts for Quiver3 {
4078 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4079 self.opts.push((key, val).into());
4080 self
4081 }
4082}
4083
4084#[derive(Clone, Debug, PartialEq)]
4098pub struct Surface {
4099 pub x: Vec<Vec<f64>>,
4101 pub y: Vec<Vec<f64>>,
4103 pub z: Vec<Vec<f64>>,
4105 pub opts: Vec<Opt>,
4107}
4108
4109impl Surface {
4110 pub fn new<XI, XJ, YI, YJ, ZI, ZJ>(x: XI, y: YI, z: ZI) -> Self
4112 where
4113 XI: IntoIterator<Item = XJ>,
4114 XJ: IntoIterator<Item = f64>,
4115 YI: IntoIterator<Item = YJ>,
4116 YJ: IntoIterator<Item = f64>,
4117 ZI: IntoIterator<Item = ZJ>,
4118 ZJ: IntoIterator<Item = f64>,
4119 {
4120 let x: Vec<Vec<f64>> =
4121 x.into_iter()
4122 .map(|row| row.into_iter().collect())
4123 .collect();
4124 let y: Vec<Vec<f64>> =
4125 y.into_iter()
4126 .map(|row| row.into_iter().collect())
4127 .collect();
4128 let z: Vec<Vec<f64>> =
4129 z.into_iter()
4130 .map(|row| row.into_iter().collect())
4131 .collect();
4132 Self { x, y, z, opts: Vec::new() }
4133 }
4134
4135 pub fn new_flat<X, Y, Z>(x: X, y: Y, z: Z, rowlen: usize) -> Self
4140 where
4141 X: IntoIterator<Item = f64>,
4142 Y: IntoIterator<Item = f64>,
4143 Z: IntoIterator<Item = f64>,
4144 {
4145 if rowlen == 0 { panic!("row length cannot be zero"); }
4146 let x: Vec<Vec<f64>> =
4147 Chunks::new(x.into_iter(), rowlen)
4148 .collect();
4149 let y: Vec<Vec<f64>> =
4150 Chunks::new(y.into_iter(), rowlen)
4151 .collect();
4152 let z: Vec<Vec<f64>> =
4153 Chunks::new(z.into_iter(), rowlen)
4154 .collect();
4155 Self { x, y, z, opts: Vec::new() }
4156 }
4157
4158 pub fn new_data<I>(data: I, rowlen: usize) -> Self
4163 where I: IntoIterator<Item = (f64, f64, f64)>
4164 {
4165 if rowlen == 0 { panic!("row length cannot be zero"); }
4166 let mut x: Vec<Vec<f64>> = Vec::new();
4167 let mut y: Vec<Vec<f64>> = Vec::new();
4168 let mut z: Vec<Vec<f64>> = Vec::new();
4169 Chunks::new(data.into_iter(), rowlen)
4170 .for_each(|points| {
4171 let mut xi: Vec<f64> = Vec::with_capacity(rowlen);
4172 let mut yi: Vec<f64> = Vec::with_capacity(rowlen);
4173 let mut zi: Vec<f64> = Vec::with_capacity(rowlen);
4174 points.into_iter()
4175 .for_each(|(xij, yij, zij)| {
4176 xi.push(xij); yi.push(yij); zi.push(zij);
4177 });
4178 x.push(xi); y.push(yi); z.push(zi);
4179 });
4180 Self { x, y, z, opts: Vec::new() }
4181 }
4182}
4183
4184pub fn surface<XI, XJ, YI, YJ, ZI, ZJ>(x: XI, y: YI, z: ZI) -> Surface
4186where
4187 XI: IntoIterator<Item = XJ>,
4188 XJ: IntoIterator<Item = f64>,
4189 YI: IntoIterator<Item = YJ>,
4190 YJ: IntoIterator<Item = f64>,
4191 ZI: IntoIterator<Item = ZJ>,
4192 ZJ: IntoIterator<Item = f64>,
4193{
4194 Surface::new(x, y, z)
4195}
4196
4197pub fn surface_flat<X, Y, Z>(x: X, y: Y, z: Z, rowlen: usize) -> Surface
4202where
4203 X: IntoIterator<Item = f64>,
4204 Y: IntoIterator<Item = f64>,
4205 Z: IntoIterator<Item = f64>,
4206{
4207 Surface::new_flat(x, y, z, rowlen)
4208}
4209
4210pub fn surface_data<I>(data: I, rowlen: usize) -> Surface
4215where I: IntoIterator<Item = (f64, f64, f64)>
4216{
4217 Surface::new_data(data, rowlen)
4218}
4219
4220impl Matplotlib for Surface {
4221 fn is_prelude(&self) -> bool { false }
4222
4223 fn data(&self) -> Option<Value> {
4224 let x: Vec<Value> =
4225 self.x.iter()
4226 .map(|row| {
4227 let row: Vec<Value> =
4228 row.iter().copied().map(Value::from).collect();
4229 Value::Array(row)
4230 })
4231 .collect();
4232 let y: Vec<Value> =
4233 self.y.iter()
4234 .map(|row| {
4235 let row: Vec<Value> =
4236 row.iter().copied().map(Value::from).collect();
4237 Value::Array(row)
4238 })
4239 .collect();
4240 let z: Vec<Value> =
4241 self.z.iter()
4242 .map(|row| {
4243 let row: Vec<Value> =
4244 row.iter().copied().map(Value::from).collect();
4245 Value::Array(row)
4246 })
4247 .collect();
4248 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
4249 }
4250
4251 fn py_cmd(&self) -> String {
4252 format!("\
4253 ax.plot_surface(\
4254 np.array(data[0]), \
4255 np.array(data[1]), \
4256 np.array(data[2])\
4257 {}{})",
4258 if self.opts.is_empty() { "" } else { ", " },
4259 self.opts.as_py(),
4260 )
4261 }
4262}
4263
4264impl MatplotlibOpts for Surface {
4265 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4266 self.opts.push((key, val).into());
4267 self
4268 }
4269}
4270
4271#[derive(Clone, Debug, PartialEq)]
4281pub struct Trisurf {
4282 pub x: Vec<f64>,
4284 pub y: Vec<f64>,
4286 pub z: Vec<f64>,
4288 pub opts: Vec<Opt>,
4290}
4291
4292impl Trisurf {
4293 pub fn new<X, Y, Z>(x: X, y: Y, z: Z) -> Self
4295 where
4296 X: IntoIterator<Item = f64>,
4297 Y: IntoIterator<Item = f64>,
4298 Z: IntoIterator<Item = f64>,
4299 {
4300 Self {
4301 x: x.into_iter().collect(),
4302 y: y.into_iter().collect(),
4303 z: z.into_iter().collect(),
4304 opts: Vec::new(),
4305 }
4306 }
4307
4308 pub fn new_data<I>(data: I) -> Self
4310 where I: IntoIterator<Item = (f64, f64, f64)>
4311 {
4312 let ((x, y), z) = data.into_iter().map(assoc).unzip();
4313 Self { x, y, z, opts: Vec::new() }
4314 }
4315}
4316
4317pub fn trisurf<X, Y, Z>(x: X, y: Y, z: Z) -> Trisurf
4319where
4320 X: IntoIterator<Item = f64>,
4321 Y: IntoIterator<Item = f64>,
4322 Z: IntoIterator<Item = f64>,
4323{
4324 Trisurf::new(x, y, z)
4325}
4326
4327pub fn trisurf_data<I>(data: I) -> Trisurf
4329where I: IntoIterator<Item = (f64, f64, f64)>
4330{
4331 Trisurf::new_data(data)
4332}
4333
4334impl Matplotlib for Trisurf {
4335 fn is_prelude(&self) -> bool { false }
4336
4337 fn data(&self) -> Option<Value> {
4338 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
4339 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
4340 let z: Vec<Value> = self.z.iter().copied().map(Value::from).collect();
4341 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
4342 }
4343
4344 fn py_cmd(&self) -> String {
4345 format!("ax.plot_trisurf(data[0], data[1], data[2]{}{})",
4346 if self.opts.is_empty() { "" } else { ", " },
4347 self.opts.as_py(),
4348 )
4349 }
4350}
4351
4352impl MatplotlibOpts for Trisurf {
4353 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4354 self.opts.push((key, val).into());
4355 self
4356 }
4357}
4358
4359#[derive(Clone, Debug, PartialEq)]
4371pub struct ViewInit {
4372 pub azim: f64,
4374 pub elev: f64,
4376 pub opts: Vec<Opt>,
4378}
4379
4380impl ViewInit {
4381 pub fn new(azim: f64, elev: f64) -> Self {
4383 Self { azim, elev, opts: Vec::new() }
4384 }
4385}
4386
4387pub fn view_init(azim: f64, elev: f64) -> ViewInit { ViewInit::new(azim, elev) }
4389
4390impl Matplotlib for ViewInit {
4391 fn is_prelude(&self) -> bool { false }
4392
4393 fn data(&self) -> Option<Value> { None }
4394
4395 fn py_cmd(&self) -> String {
4396 format!("ax.view_init(azim={}, elev={}{}{})",
4397 self.azim,
4398 self.elev,
4399 if self.opts.is_empty() { "" } else { ", " },
4400 self.opts.as_py(),
4401 )
4402 }
4403}
4404
4405impl MatplotlibOpts for ViewInit {
4406 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4407 self.opts.push((key, val).into());
4408 self
4409 }
4410}
4411
4412pub trait Associator<P> {
4448 fn assoc(self) -> P;
4450}
4451
4452impl<A, B, C> Associator<((A, B), C)> for (A, B, C) {
4456 fn assoc(self) -> ((A, B), C) { ((self.0, self.1), self.2) }
4457}
4458
4459impl<A, B, C> Associator<(A, B, C)> for ((A, B), C) {
4460 fn assoc(self) -> (A, B, C) { (self.0.0, self.0.1, self.1) }
4461}
4462
4463impl<A, B, C> Associator<(A, (B, C))> for (A, B, C) {
4464 fn assoc(self) -> (A, (B, C)) { (self.0, (self.1, self.2)) }
4465}
4466
4467impl<A, B, C> Associator<(A, B, C)> for (A, (B, C)) {
4468 fn assoc(self) -> (A, B, C) { (self.0, self.1.0, self.1.1) }
4469}
4470
4471macro_rules! impl_biassoc {
4474 (
4475 <$( $gen:ident ),+>,
4476 $pair:ty,
4477 ($( $l:ident ),+),
4478 $r:ident $(,)?
4479 ) => {
4480 impl<$( $gen ),+> Associator<$pair> for ($( $gen ),+) {
4481 fn assoc(self) -> $pair {
4482 let ($( $l ),+, $r) = self;
4483 (($( $l ),+).assoc(), $r)
4484 }
4485 }
4486
4487 impl<$( $gen ),+> Associator<($( $gen ),+)> for $pair {
4488 fn assoc(self) -> ($( $gen ),+) {
4489 let ($( $l ),+) = self.0.assoc();
4490 ($( $l ),+, self.1)
4491 }
4492 }
4493 };
4494 (
4495 <$( $gen:ident ),+>,
4496 $pair:ty,
4497 $l:ident,
4498 ($( $r:ident ),+) $(,)?
4499 ) => {
4500 impl<$( $gen ),+> Associator<$pair> for ($( $gen ),+) {
4501 fn assoc(self) -> $pair {
4502 let ($l, $( $r ),+) = self;
4503 ($l, ($( $r ),+).assoc())
4504 }
4505 }
4506
4507 impl<$( $gen ),+> Associator<($( $gen ),+)> for $pair {
4508 fn assoc(self) -> ($( $gen ),+) {
4509 let ($( $r ),+) = self.1.assoc();
4510 (self.0, $( $r ),+)
4511 }
4512 }
4513 };
4514}
4515
4516impl_biassoc!(<A, B, C, D>, (((A, B), C), D), (a, b, c), d);
4517impl_biassoc!(<A, B, C, D>, ((A, (B, C)), D), (a, b, c), d);
4518impl_biassoc!(<A, B, C, D>, (A, ((B, C), D)), a, (b, c, d));
4519impl_biassoc!(<A, B, C, D>, (A, (B, (C, D))), a, (b, c, d));
4520impl_biassoc!(<A, B, C, D, E>, ((((A, B), C), D), E), (a, b, c, d), e);
4521impl_biassoc!(<A, B, C, D, E>, (((A, (B, C)), D), E), (a, b, c, d), e);
4522impl_biassoc!(<A, B, C, D, E>, ((A, ((B, C), D)), E), (a, b, c, d), e);
4523impl_biassoc!(<A, B, C, D, E>, ((A, (B, (C, D))), E), (a, b, c, d), e);
4524impl_biassoc!(<A, B, C, D, E>, (A, (((B, C), D), E)), a, (b, c, d, e));
4525impl_biassoc!(<A, B, C, D, E>, (A, ((B, (C, D)), E)), a, (b, c, d, e));
4526impl_biassoc!(<A, B, C, D, E>, (A, (B, ((C, D), E))), a, (b, c, d, e));
4527impl_biassoc!(<A, B, C, D, E>, (A, (B, (C, (D, E)))), a, (b, c, d, e));
4528impl_biassoc!(<A, B, C, D, E, F>, (((((A, B), C), D), E), F), (a, b, c, d, e), f);
4529impl_biassoc!(<A, B, C, D, E, F>, ((((A, (B, C)), D), E), F), (a, b, c, d, e), f);
4530impl_biassoc!(<A, B, C, D, E, F>, (((A, ((B, C), D)), E), F), (a, b, c, d, e), f);
4531impl_biassoc!(<A, B, C, D, E, F>, (((A, (B, (C, D))), E), F), (a, b, c, d, e), f);
4532impl_biassoc!(<A, B, C, D, E, F>, ((A, (((B, C), D), E)), F), (a, b, c, d, e), f);
4533impl_biassoc!(<A, B, C, D, E, F>, ((A, ((B, (C, D)), E)), F), (a, b, c, d, e), f);
4534impl_biassoc!(<A, B, C, D, E, F>, ((A, (B, ((C, D), E))), F), (a, b, c, d, e), f);
4535impl_biassoc!(<A, B, C, D, E, F>, ((A, (B, (C, (D, E)))), F), (a, b, c, d, e), f);
4536impl_biassoc!(<A, B, C, D, E, F>, (A, ((((B, C), D), E), F)), a, (b, c, d, e, f));
4537impl_biassoc!(<A, B, C, D, E, F>, (A, (((B, (C, D)), E), F)), a, (b, c, d, e, f));
4538impl_biassoc!(<A, B, C, D, E, F>, (A, ((B, ((C, D), E)), F)), a, (b, c, d, e, f));
4539impl_biassoc!(<A, B, C, D, E, F>, (A, ((B, (C, (D, E))), F)), a, (b, c, d, e, f));
4540impl_biassoc!(<A, B, C, D, E, F>, (A, (B, (((C, D), E), F))), a, (b, c, d, e, f));
4541impl_biassoc!(<A, B, C, D, E, F>, (A, (B, ((C, (D, E)), F))), a, (b, c, d, e, f));
4542impl_biassoc!(<A, B, C, D, E, F>, (A, (B, (C, ((D, E), F)))), a, (b, c, d, e, f));
4543impl_biassoc!(<A, B, C, D, E, F>, (A, (B, (C, (D, (E, F))))), a, (b, c, d, e, f));
4544
4545pub fn assoc<A, B>(a: A) -> B
4548where A: Associator<B>
4549{
4550 a.assoc()
4551}
4552
4553pub fn assoc_iter<I, J, A, B>(iter: I) -> std::iter::Map<J, fn(A) -> B>
4555where
4556 I: IntoIterator<IntoIter = J, Item = A>,
4557 J: Iterator<Item = A>,
4558 A: Associator<B>,
4559{
4560 iter.into_iter().map(assoc)
4561}
4562
4563#[cfg(test)]
4564mod tests {
4565 use crate::{ Mpl, Run, MatplotlibOpts, opt, GSPos };
4566 use super::*;
4567
4568 fn runner() -> Run { Run::Debug }
4569
4570 #[test]
4571 fn test_prelude_init() {
4572 Mpl::default()
4573 & DefPrelude
4574 & DefInit
4575 | runner()
4576 }
4577
4578 #[test]
4579 fn test_axhline() {
4580 Mpl::default()
4581 & axhline(10.0).o("linestyle", "-")
4582 | runner()
4583 }
4584
4585 #[test]
4586 fn test_axline() {
4587 Mpl::default()
4588 & axline((0.0, 0.0), (10.0, 10.0)).o("linestyle", "-")
4589 | runner()
4590 }
4591
4592 #[test]
4593 fn test_axlinem() {
4594 Mpl::default()
4595 & axlinem((0.0, 0.0), 1.0).o("linestyle", "-")
4596 | runner()
4597 }
4598
4599 #[test]
4600 fn test_axtext() {
4601 Mpl::default()
4602 & axtext(0.5, 0.5, "hello world").o("ha", "left").o("va", "bottom")
4603 | runner()
4604 }
4605
4606 #[test]
4607 fn test_axvline() {
4608 Mpl::default()
4609 & axvline(10.0).o("linestyle", "-")
4610 | runner()
4611 }
4612
4613 #[test]
4614 fn test_bar() {
4615 Mpl::default()
4616 & bar([0.0, 1.0], [0.5, 0.5]).o("color", "C0")
4617 | runner()
4618 }
4619
4620 #[test]
4621 fn test_bar_pairs() {
4622 Mpl::default()
4623 & bar_pairs([(0.0, 0.5), (1.0, 0.5)]).o("color", "C0")
4624 | runner()
4625 }
4626
4627 #[test]
4628 fn test_bar_eq() {
4629 assert_eq!(
4630 bar([0.0, 1.0], [0.5, 0.5]).o("color", "C0"),
4631 bar_pairs([(0.0, 0.5), (1.0, 0.5)]).o("color", "C0"),
4632 )
4633 }
4634
4635 #[test]
4636 fn test_barh() {
4637 Mpl::default()
4638 & barh([0.0, 1.0], [0.5, 0.5]).o("color", "C0")
4639 | runner()
4640 }
4641
4642 #[test]
4643 fn test_barh_pairs() {
4644 Mpl::default()
4645 & barh_pairs([(0.0, 0.5), (1.0, 0.5)]).o("color", "C0")
4646 | runner()
4647 }
4648
4649 #[test]
4650 fn test_barh_eq() {
4651 assert_eq!(
4652 barh([0.0, 1.0], [0.5, 0.5]).o("color", "C0"),
4653 barh_pairs([(0.0, 0.5), (1.0, 0.5)]).o("color", "C0"),
4654 )
4655 }
4656
4657 #[test]
4658 fn test_boxplot() {
4659 Mpl::default()
4660 & boxplot([[0.0, 1.0, 2.0], [2.0, 3.0, 4.0]]).o("notch", true)
4661 | runner()
4662 }
4663
4664 #[test]
4665 fn test_boxplot_flat() {
4666 Mpl::default()
4667 & boxplot_flat([0.0, 1.0, 2.0, 2.0, 3.0, 4.0], 3).o("notch", true)
4668 | runner()
4669 }
4670
4671 #[test]
4672 fn test_boxplot_eq() {
4673 assert_eq!(
4674 boxplot([[0.0, 1.0, 2.0], [2.0, 3.0, 4.0]]).o("notch", true),
4675 boxplot_flat([0.0, 1.0, 2.0, 2.0, 3.0, 4.0], 3).o("notch", true),
4676 )
4677 }
4678
4679 #[test]
4680 fn test_clabel() {
4681 Mpl::default()
4682 & imshow([[0.0, 1.0], [2.0, 3.0]])
4683 & colorbar()
4684 & clabel("hello world").o("fontsize", "medium")
4685 | runner()
4686 }
4687
4688 #[test]
4689 fn test_clim() {
4690 Mpl::default()
4691 & imshow([[0.0, 1.0], [2.0, 3.0]])
4692 & colorbar()
4693 & clim(Some(0.0), Some(1.0))
4694 | runner()
4695 }
4696
4697 #[test]
4698 fn test_colorbar() {
4699 Mpl::default()
4700 & imshow([[0.0, 1.0], [2.0, 3.0]])
4701 & colorbar().o("location", "top")
4702 | runner()
4703 }
4704
4705 #[test]
4706 fn test_contour() {
4707 Mpl::default()
4708 & contour([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
4709 .o("cmap", "bone")
4710 & colorbar()
4711 | runner()
4712 }
4713
4714 #[test]
4715 fn test_contour_flat() {
4716 Mpl::default()
4717 & contour_flat([0.0, 1.0], [0.0, 1.0], [0.0, 1.0, 2.0, 3.0])
4718 .o("cmap", "bone")
4719 & colorbar()
4720 | runner()
4721 }
4722
4723 #[test]
4724 fn test_contour_eq() {
4725 assert_eq!(
4726 contour([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
4727 .o("cmap", "bone"),
4728 contour_flat([0.0, 1.0], [0.0, 1.0], [0.0, 1.0, 2.0, 3.0])
4729 .o("cmap", "bone"),
4730 )
4731 }
4732
4733 #[test]
4734 fn test_contourf() {
4735 Mpl::default()
4736 & contour([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
4737 .o("cmap", "bone")
4738 & colorbar()
4739 | runner()
4740 }
4741
4742 #[test]
4743 fn test_contourf_flat() {
4744 Mpl::default()
4745 & contour_flat([0.0, 1.0], [0.0, 1.0], [0.0, 1.0, 2.0, 3.0])
4746 .o("cmap", "bone")
4747 & colorbar()
4748 | runner()
4749 }
4750
4751 #[test]
4752 fn test_contourf_eq() {
4753 assert_eq!(
4754 contourf([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
4755 .o("cmap", "bone"),
4756 contourf_flat([0.0, 1.0], [0.0, 1.0], [0.0, 1.0, 2.0, 3.0])
4757 .o("cmap", "bone"),
4758 )
4759 }
4760
4761 #[test]
4762 fn test_cticklabels() {
4763 Mpl::default()
4764 & imshow([[0.0, 1.0], [2.0, 3.0]])
4765 & colorbar()
4766 & cticklabels([0.0, 1.0], ["zero", "one"]).o("minor", true)
4767 | runner()
4768 }
4769
4770 #[test]
4771 fn test_cticklabels_data() {
4772 Mpl::default()
4773 & imshow([[0.0, 1.0], [2.0, 3.0]])
4774 & colorbar()
4775 & cticklabels_data([(0.0, "zero"), (1.0, "one")]).o("minor", true)
4776 | runner()
4777 }
4778
4779 #[test]
4780 fn test_cticklabels_eq() {
4781 assert_eq!(
4782 cticklabels([0.0, 1.0], ["zero", "one"]).o("minor", true),
4783 cticklabels_data([(0.0, "zero"), (1.0, "one")]).o("minor", true),
4784 )
4785 }
4786
4787 #[test]
4788 fn test_cticks() {
4789 Mpl::default()
4790 & imshow([[0.0, 1.0], [2.0, 3.0]])
4791 & colorbar()
4792 & cticks([0.0, 1.0])
4793 .o("labels", PyValue::list(["zero", "one"]))
4794 | runner()
4795 }
4796
4797 #[test]
4798 fn test_errorbar() {
4799 Mpl::default()
4800 & errorbar([0.0, 1.0], [0.0, 1.0], [0.5, 1.0]).o("color", "C0")
4801 | runner()
4802 }
4803
4804 #[test]
4805 fn test_errorbar_data() {
4806 Mpl::default()
4807 & errorbar_data([(0.0, 0.0, 0.5), (1.0, 1.0, 1.0)]).o("color", "C0")
4808 | runner()
4809 }
4810
4811 #[test]
4812 fn test_errorbar_eq() {
4813 assert_eq!(
4814 errorbar([0.0, 1.0], [0.0, 1.0], [0.5, 1.0]).o("color", "C0"),
4815 errorbar_data([(0.0, 0.0, 0.5), (1.0, 1.0, 1.0)]).o("color", "C0"),
4816 )
4817 }
4818
4819 #[test]
4820 fn test_errorbar2() {
4821 Mpl::default()
4822 & errorbar2([0.0, 1.0], [0.0, 1.0], [1.0, 0.5], [0.5, 1.0])
4823 .o("color", "C0")
4824 | runner()
4825 }
4826
4827 #[test]
4828 fn test_errorbar2_data() {
4829 Mpl::default()
4830 & errorbar2_data([(0.0, 0.0, 1.0, 0.5), (1.0, 1.0, 0.5, 1.0)])
4831 .o("color", "C0")
4832 | runner()
4833 }
4834
4835 #[test]
4836 fn test_errorbar2_eq() {
4837 assert_eq!(
4838 errorbar2([0.0, 1.0], [0.0, 1.0], [1.0, 0.5], [0.5, 1.0])
4839 .o("color", "C0"),
4840 errorbar2_data([(0.0, 0.0, 1.0, 0.5), (1.0, 1.0, 0.5, 1.0)])
4841 .o("color", "C0"),
4842 )
4843 }
4844
4845 #[test]
4846 fn test_figtext() {
4847 Mpl::default()
4848 & figtext(0.5, 0.5, "hello world").o("ha", "left").o("va", "bottom")
4849 | runner()
4850 }
4851
4852 #[test]
4853 fn test_fill_between() {
4854 Mpl::default()
4855 & fill_between([0.0, 1.0], [-0.5, 0.0], [0.5, 2.0]).o("color", "C0")
4856 | runner()
4857 }
4858
4859 #[test]
4860 fn test_fill_between_data() {
4861 Mpl::default()
4862 & fill_between_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)])
4863 .o("color", "C0")
4864 | runner()
4865 }
4866
4867 #[test]
4868 fn test_fill_between_eq() {
4869 assert_eq!(
4870 fill_between([0.0, 1.0], [-0.5, 0.0], [0.5, 2.0]).o("color", "C0"),
4871 fill_between_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)])
4872 .o("color", "C0"),
4873 )
4874 }
4875
4876 #[test]
4877 fn test_fillbetween_from_errorbar() {
4878 let ebar =
4879 errorbar_data([(0.0, 0.0, 0.5), (1.0, 1.0, 1.0)]);
4880 let ebar2 =
4881 errorbar2_data([(0.0, 0.25, 0.75, 0.25), (1.0, 1.0, 1.0, 1.0)]);
4882 let fbetw =
4883 fill_between_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)]);
4884 assert_eq!(FillBetween::from(ebar), fbetw);
4885 assert_eq!(FillBetween::from(ebar2), fbetw);
4886 }
4887
4888 #[test]
4889 fn test_errorbar_from_fillbetween() {
4890 let fbetw = fill_between_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)]);
4891 let ebar = errorbar_data([(0.0, 0.0, 0.5), (1.0, 1.0, 1.0)]);
4892 assert_eq!(Errorbar::from(fbetw), ebar);
4893 }
4894
4895 #[test]
4896 fn test_fill_betweenx() {
4897 Mpl::default()
4898 & fill_betweenx([0.0, 1.0], [-0.5, 0.0], [0.5, 2.0])
4899 .o("color", "C0")
4900 | runner()
4901 }
4902
4903 #[test]
4904 fn test_fill_betweenx_data() {
4905 Mpl::default()
4906 & fill_betweenx_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)])
4907 .o("color", "C0")
4908 | runner()
4909 }
4910
4911 #[test]
4912 fn test_fill_betweenx_eq() {
4913 assert_eq!(
4914 fill_betweenx([0.0, 1.0], [-0.5, 0.0], [0.5, 2.0]).o("color", "C0"),
4915 fill_betweenx_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)])
4916 .o("color", "C0"),
4917 )
4918 }
4919
4920 #[test]
4921 fn test_grid() {
4922 Mpl::default()
4923 & grid(true).o("which", "both")
4924 | runner()
4925 }
4926
4927 #[test]
4928 fn test_hist() {
4929 Mpl::default()
4930 & hist([0.0, 1.0, 2.0])
4931 .o("bins", PyValue::list([-0.5, 0.5, 1.5, 2.5]))
4932 | runner()
4933 }
4934
4935 #[test]
4936 fn test_hist2d() {
4937 Mpl::default()
4938 & hist2d([0.0, 1.0, 2.0], [0.0, 2.0, 4.0]).o("cmap", "bone")
4939 | runner()
4940 }
4941
4942 #[test]
4943 fn test_hist2d_pairs() {
4944 Mpl::default()
4945 & hist2d_pairs([(0.0, 0.0), (1.0, 2.0), (2.0, 4.0)])
4946 .o("cmap", "bone")
4947 | runner()
4948 }
4949
4950 #[test]
4951 fn test_hist2d_eq() {
4952 assert_eq!(
4953 hist2d([0.0, 1.0, 2.0], [0.0, 2.0, 4.0]).o("cmap", "bone"),
4954 hist2d_pairs([(0.0, 0.0), (1.0, 2.0), (2.0, 4.0)]).o("cmap", "bone"),
4955 )
4956 }
4957
4958 #[test]
4959 fn test_violinplot() {
4960 Mpl::default()
4961 & violinplot([[0.0, 1.0], [2.0, 3.0]]).o("vert", false)
4962 | runner()
4963 }
4964
4965 #[test]
4966 fn test_violinplot_flat() {
4967 Mpl::default()
4968 & violinplot_flat([0.0, 1.0, 2.0, 3.0], 2).o("vert", false)
4969 | runner()
4970 }
4971
4972 #[test]
4973 fn test_violinplot_eq() {
4974 assert_eq!(
4975 violinplot([[0.0, 1.0], [2.0, 3.0]]).o("vert", false),
4976 violinplot_flat([0.0, 1.0, 2.0, 3.0], 2).o("vert", false),
4977 )
4978 }
4979
4980 #[test]
4981 fn test_imshow() {
4982 Mpl::default()
4983 & imshow([[0.0, 1.0], [2.0, 3.0]]).o("cmap", "bone")
4984 | runner()
4985 }
4986
4987 #[test]
4988 fn test_imshow_flat() {
4989 Mpl::default()
4990 & imshow_flat([0.0, 1.0, 2.0, 3.0], 2).o("cmap", "bone")
4991 | runner()
4992 }
4993
4994 #[test]
4995 fn test_imshow_eq() {
4996 assert_eq!(
4997 imshow([[0.0, 1.0], [2.0, 3.0]]).o("cmap", "bone"),
4998 imshow_flat([0.0, 1.0, 2.0, 3.0], 2).o("cmap", "bone"),
4999 )
5000 }
5001
5002 #[test]
5003 fn test_inset_axes() {
5004 Mpl::default()
5005 & inset_axes(0.5, 0.5, 0.25, 0.25).o("polar", true)
5006 | runner()
5007 }
5008
5009 #[test]
5010 fn test_inset_axes_pairs() {
5011 Mpl::default()
5012 & inset_axes_pairs((0.5, 0.5), (0.25, 0.25)).o("polar", true)
5013 | runner()
5014 }
5015
5016 #[test]
5017 fn test_label() {
5018 Mpl::default()
5019 & label(Axis::X, "xlabel").o("fontsize", "large")
5020 & label(Axis::Y, "ylabel").o("fontsize", "large")
5021 | runner()
5022 }
5023
5024 #[test]
5025 fn test_xlabel() {
5026 Mpl::default()
5027 & xlabel("xlabel").o("fontsize", "large")
5028 | runner()
5029 }
5030
5031 #[test]
5032 fn test_ylabel() {
5033 Mpl::default()
5034 & ylabel("ylabel").o("fontsize", "large")
5035 | runner()
5036 }
5037
5038 #[test]
5039 fn test_label_eq() {
5040 assert_eq!(label(Axis::X, "xlabel"), xlabel("xlabel"));
5041 assert_eq!(label(Axis::Y, "ylabel"), ylabel("ylabel"));
5042 }
5043
5044 #[test]
5045 fn test_legend() {
5046 Mpl::default()
5047 & plot([0.0], [0.0]).o("label", "hello world")
5048 & legend().o("loc", "lower left")
5049 | runner()
5050 }
5051
5052 #[test]
5053 fn test_lim() {
5054 Mpl::default()
5055 & lim(Axis::X, Some(-10.0), Some(10.0))
5056 & lim(Axis::Y, Some(-10.0), Some(10.0))
5057 | runner()
5058 }
5059
5060 #[test]
5061 fn test_xlim() {
5062 Mpl::default()
5063 & xlim(Some(-10.0), Some(10.0))
5064 | runner()
5065 }
5066
5067 #[test]
5068 fn test_ylim() {
5069 Mpl::default()
5070 & ylim(Some(-10.0), Some(10.0))
5071 | runner()
5072 }
5073
5074 #[test]
5075 fn test_lim_eq() {
5076 assert_eq!(
5077 lim(Axis::X, Some(-10.0), Some(15.0)),
5078 xlim(Some(-10.0), Some(15.0)),
5079 );
5080 assert_eq!(
5081 lim(Axis::Y, Some(-10.0), Some(15.0)),
5082 ylim(Some(-10.0), Some(15.0)),
5083 );
5084 assert_eq!(
5085 lim(Axis::Z, Some(-10.0), Some(15.0)),
5086 zlim(Some(-10.0), Some(15.0)),
5087 )
5088 }
5089
5090 #[test]
5091 fn test_pie() {
5092 Mpl::default()
5093 & pie([1.0, 2.0]).o("radius", 2)
5094 | runner()
5095 }
5096
5097 #[test]
5098 fn test_plot() {
5099 Mpl::default()
5100 & plot([0.0, 1.0], [0.0, 1.0]).o("color", "C0")
5101 | runner()
5102 }
5103
5104 #[test]
5105 fn test_plot_pairs() {
5106 Mpl::default()
5107 & plot_pairs([(0.0, 0.0), (1.0, 1.0)]).o("color", "C0")
5108 | runner()
5109 }
5110
5111 #[test]
5112 fn test_plot_eq() {
5113 assert_eq!(
5114 plot([0.0, 1.0], [0.0, 1.0]).o("color", "C0"),
5115 plot_pairs([(0.0, 0.0), (1.0, 1.0)]).o("color", "C0"),
5116 )
5117 }
5118
5119 #[test]
5120 fn test_quiver() {
5121 Mpl::default()
5122 & quiver([0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0])
5123 .o("pivot", "middle")
5124 | runner()
5125 }
5126
5127 #[test]
5128 fn test_quiver_data() {
5129 Mpl::default()
5130 & quiver_data([(0.0, 0.0, 0.0, 0.0), (1.0, 1.0, 1.0, 1.0)])
5131 .o("pivot", "middle")
5132 | runner()
5133 }
5134
5135 #[test]
5136 fn test_quiver_pairs() {
5137 Mpl::default()
5138 & quiver_pairs([(0.0, 0.0), (1.0, 1.0)], [(0.0, 0.0), (1.0, 1.0)])
5139 .o("pivot", "middle")
5140 | runner()
5141 }
5142
5143 #[test]
5144 fn test_quiver_eq() {
5145 let norm =
5146 quiver([0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0])
5147 .o("pivot", "middle");
5148 let data =
5149 quiver_data([(0.0, 0.0, 0.0, 0.0), (1.0, 1.0, 1.0, 1.0)])
5150 .o("pivot", "middle");
5151 let pairs =
5152 quiver_pairs([(0.0, 0.0), (1.0, 1.0)], [(0.0, 0.0), (1.0, 1.0)])
5153 .o("pivot", "middle");
5154 assert_eq!(norm, data);
5155 assert_eq!(norm, pairs);
5156 }
5157
5158 #[test]
5159 fn test_rcparam() {
5160 Mpl::default()
5161 & rcparam("figure.figsize", PyValue::list([2.5, 3.5]))
5162 | runner()
5163 }
5164
5165 #[test]
5166 fn test_scale() {
5167 Mpl::default()
5168 & scale(Axis::X, AxisScale::Log)
5169 & scale(Axis::Y, AxisScale::Logit)
5170 | runner()
5171 }
5172
5173 #[test]
5174 fn test_xscale() {
5175 Mpl::default()
5176 & xscale(AxisScale::Log)
5177 | runner()
5178 }
5179
5180 #[test]
5181 fn test_yscale() {
5182 Mpl::default()
5183 & yscale(AxisScale::Logit)
5184 | runner()
5185 }
5186
5187 #[test]
5188 fn test_scale_eq() {
5189 assert_eq!(scale(Axis::X, AxisScale::Log), xscale(AxisScale::Log));
5190 assert_eq!(scale(Axis::Y, AxisScale::Logit), yscale(AxisScale::Logit));
5191 assert_eq!(scale(Axis::Z, AxisScale::SymLog), zscale(AxisScale::SymLog));
5192 }
5193
5194 #[test]
5195 fn test_scatter() {
5196 Mpl::default()
5197 & scatter([0.0, 1.0], [0.0, 1.0]).o("marker", "D")
5198 | runner()
5199 }
5200
5201 #[test]
5202 fn test_scatter_pairs() {
5203 Mpl::default()
5204 & scatter_pairs([(0.0, 0.0), (1.0, 1.0)]).o("marker", "D")
5205 | runner()
5206 }
5207
5208 #[test]
5209 fn test_scatter_eq() {
5210 assert_eq!(
5211 scatter([0.0, 1.0], [0.0, 1.0]).o("marker", "D"),
5212 scatter_pairs([(0.0, 0.0), (1.0, 1.0)]).o("marker", "D"),
5213 )
5214 }
5215
5216 #[test]
5217 fn test_suptitle() {
5218 Mpl::default()
5219 & suptitle("hello world").o("fontsize", "xx-small")
5220 | runner()
5221 }
5222
5223 #[test]
5224 fn test_supxlabel() {
5225 Mpl::default()
5226 & supxlabel("hello world").o("fontsize", "xx-small")
5227 | runner()
5228 }
5229
5230 #[test]
5231 fn test_supylabel() {
5232 Mpl::default()
5233 & supylabel("hello world").o("fontsize", "xx-small")
5234 | runner()
5235 }
5236
5237 #[test]
5238 fn test_make_grid() {
5239 Mpl::new_grid(3, 3, [opt("sharex", true), opt("sharey", true)])
5240 & focus_ax("AX[1, 1]")
5241 & plot([0.0, 1.0], [0.0, 1.0]).o("color", "C1")
5242 | runner()
5243 }
5244
5245 #[test]
5246 fn test_make_gridspec() {
5247 Mpl::new_gridspec(
5261 [
5262 opt("nrows", 3),
5263 opt("ncols", 3),
5264 opt("width_ratios", PyValue::list([1, 1, 2])),
5265 ],
5266 [
5267 GSPos::new(0..2, 0..2),
5268 GSPos::new(2..3, 0..2).sharex(Some(0)),
5269 GSPos::new(0..3, 2..3),
5270 ],
5271 )
5272 & focus_ax("AX[1]")
5273 & plot([0.0, 1.0], [0.0, 1.0]).o("color", "C1")
5274 | runner()
5275 }
5276
5277 #[test]
5278 fn test_tex_off() {
5279 Mpl::default()
5280 & DefPrelude
5281 & tex_off()
5282 | runner()
5283 }
5284
5285 #[test]
5286 fn test_tex_on() {
5287 Mpl::default()
5288 & DefPrelude
5289 & tex_on()
5290 | runner()
5291 }
5292
5293 #[test]
5294 fn test_text() {
5295 Mpl::default()
5296 & text(0.5, 0.5, "hello world").o("fontsize", "large")
5297 | runner()
5298 }
5299
5300 #[test]
5301 fn test_tick_params() {
5302 Mpl::default()
5303 & tick_params(Axis2::Both).o("color", "r")
5304 | runner()
5305 }
5306
5307 #[test]
5308 fn test_xtick_params() {
5309 Mpl::default()
5310 & xtick_params().o("color", "r")
5311 | runner()
5312 }
5313
5314 #[test]
5315 fn test_ytick_params() {
5316 Mpl::default()
5317 & xtick_params().o("color", "r")
5318 | runner()
5319 }
5320
5321 #[test]
5322 fn test_tick_params_eq() {
5323 assert_eq!(
5324 tick_params(Axis2::X).o("color", "r"),
5325 xtick_params().o("color", "r"),
5326 );
5327 assert_eq!(
5328 tick_params(Axis2::Y).o("color", "r"),
5329 ytick_params().o("color", "r"),
5330 );
5331 }
5332
5333 #[test]
5334 fn test_ticklabels() {
5335 Mpl::default()
5336 & ticklabels(Axis::X, [0.0, 1.0], ["x:zero", "x:one"])
5337 .o("fontsize", "small")
5338 & ticklabels(Axis::Y, [0.0, 1.0], ["y:zero", "y:one"])
5339 .o("fontsize", "small")
5340 | runner()
5341 }
5342
5343 #[test]
5344 fn test_ticklabels_data() {
5345 Mpl::default()
5346 & ticklabels_data(Axis::X, [(0.0, "x:zero"), (1.0, "x:one")])
5347 .o("fontsize", "small")
5348 & ticklabels_data(Axis::Y, [(0.0, "y:zero"), (1.0, "y:one")])
5349 .o("fontsize", "small")
5350 | runner()
5351 }
5352
5353 #[test]
5354 fn test_xticklabels() {
5355 Mpl::default()
5356 & xticklabels([0.0, 1.0], ["x:zero", "x:one"])
5357 .o("fontsize", "small")
5358 | runner()
5359 }
5360
5361 #[test]
5362 fn test_xticklabels_data() {
5363 Mpl::default()
5364 & xticklabels_data([(0.0, "x:zero"), (1.0, "x:one")])
5365 .o("fontsize", "small")
5366 | runner()
5367 }
5368
5369 #[test]
5370 fn test_yticklabels() {
5371 Mpl::default()
5372 & yticklabels([0.0, 1.0], ["y:zero", "y:one"])
5373 .o("fontsize", "small")
5374 | runner()
5375 }
5376
5377 #[test]
5378 fn test_yticklabels_data() {
5379 Mpl::default()
5380 & yticklabels_data([(0.0, "y:zero"), (1.0, "y:one")])
5381 .o("fontsize", "small")
5382 | runner()
5383 }
5384
5385 #[test]
5386 fn test_ticklabels_eq() {
5387 let normx =
5388 ticklabels(Axis::X, [0.0, 1.0], ["x:zero", "x:one"]);
5389 let normx_data =
5390 ticklabels_data(Axis::X, [(0.0, "x:zero"), (1.0, "x:one")]);
5391 let aliasx =
5392 xticklabels([0.0, 1.0], ["x:zero", "x:one"]);
5393 let aliasx_data =
5394 xticklabels_data([(0.0, "x:zero"), (1.0, "x:one")]);
5395 let normy =
5396 ticklabels(Axis::Y, [0.0, 1.0], ["y:zero", "y:one"]);
5397 let normy_data =
5398 ticklabels_data(Axis::Y, [(0.0, "y:zero"), (1.0, "y:one")]);
5399 let aliasy =
5400 yticklabels([0.0, 1.0], ["y:zero", "y:one"]);
5401 let aliasy_data =
5402 yticklabels_data([(0.0, "y:zero"), (1.0, "y:one")]);
5403 assert_eq!(normx, normx_data);
5404 assert_eq!(aliasx, aliasx_data);
5405 assert_eq!(normx, aliasx);
5406 assert_eq!(normy, normy_data);
5407 assert_eq!(aliasy, aliasy_data);
5408 assert_eq!(normy, aliasy);
5409 }
5410
5411 #[test]
5412 fn test_ticks() {
5413 Mpl::default()
5414 & ticks(Axis::X, [0.0, 1.0]).o("minor", true)
5415 & ticks(Axis::Y, [0.0, 2.0]).o("minor", true)
5416 | runner()
5417 }
5418
5419 #[test]
5420 fn test_xticks() {
5421 Mpl::default()
5422 & xticks([0.0, 1.0]).o("minor", true)
5423 | runner()
5424 }
5425
5426 #[test]
5427 fn test_yticks() {
5428 Mpl::default()
5429 & yticks([0.0, 2.0]).o("minor", true)
5430 | runner()
5431 }
5432
5433 #[test]
5434 fn test_ticks_eq() {
5435 let normx = ticks(Axis::X, [0.0, 1.0]);
5436 let aliasx = xticks([0.0, 1.0]);
5437 let normy = ticks(Axis::Y, [0.0, 2.0]);
5438 let aliasy = yticks([0.0, 2.0]);
5439 assert_eq!(normx, aliasx);
5440 assert_eq!(normy, aliasy);
5441 }
5442
5443 #[test]
5444 fn test_title() {
5445 Mpl::default()
5446 & title("hello world").o("fontsize", "large")
5447 | runner()
5448 }
5449
5450 #[test]
5451 fn test_tight_layout() {
5452 Mpl::new_grid(3, 3, [])
5453 & tight_layout().o("h_pad", 1.0).o("w_pad", 0.5)
5454 | runner()
5455 }
5456
5457 #[test]
5458 fn test_make_3d() {
5459 Mpl::new_3d([opt("elev", 50.0)])
5460 | runner()
5461 }
5462
5463 #[test]
5464 fn test_plot3() {
5465 Mpl::new_3d([])
5466 & plot3([0.0, 1.0], [0.0, 1.0], [0.0, 1.0]).o("marker", "D")
5467 | runner()
5468 }
5469
5470 #[test]
5471 fn test_plot3_data() {
5472 Mpl::new_3d([])
5473 & plot3_data([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]).o("marker", "D")
5474 | runner()
5475 }
5476
5477 #[test]
5478 fn test_plot3_eq() {
5479 assert_eq!(
5480 plot3([0.0, 1.0], [0.0, 1.0], [0.0, 1.0]).o("marker", "D"),
5481 plot3_data([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]).o("marker", "D"),
5482 )
5483 }
5484
5485 #[test]
5486 fn test_scatter3() {
5487 Mpl::new_3d([])
5488 & scatter3([0.0, 1.0], [0.0, 1.0], [0.0, 1.0]).o("marker", "D")
5489 | runner()
5490 }
5491
5492 #[test]
5493 fn test_scatter3_data() {
5494 Mpl::new_3d([])
5495 & scatter3_data([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]).o("marker", "D")
5496 | runner()
5497 }
5498
5499 #[test]
5500 fn test_scatter3_eq() {
5501 assert_eq!(
5502 scatter3([0.0, 1.0], [0.0, 1.0], [0.0, 1.0]).o("marker", "D"),
5503 scatter3_data([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]).o("marker", "D"),
5504 )
5505 }
5506
5507 #[test]
5508 fn test_quiver3() {
5509 Mpl::new_3d([])
5510 & quiver3(
5511 [0.0, 1.0],
5512 [0.0, 1.0],
5513 [0.0, 1.0],
5514 [1.0, 2.0],
5515 [1.0, 2.0],
5516 [1.0, 2.0],
5517 ).o("pivot", "middle")
5518 | runner()
5519 }
5520
5521 #[test]
5522 fn test_quiver3_data() {
5523 Mpl::new_3d([])
5524 & quiver3_data([
5525 (0.0, 0.0, 0.0, 1.0, 1.0, 1.0),
5526 (1.0, 1.0, 1.0, 2.0, 2.0, 2.0),
5527 ]).o("pivot", "middle")
5528 | runner()
5529 }
5530
5531 #[test]
5532 fn test_quiver3_triples() {
5533 Mpl::new_3d([])
5534 & quiver3_triples(
5535 [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
5536 [(1.0, 1.0, 1.0), (2.0, 2.0, 2.0)],
5537 ).o("pivot", "middle")
5538 | runner()
5539 }
5540
5541 #[test]
5542 fn test_quiver3_eq() {
5543 let norm = quiver3(
5544 [0.0, 1.0],
5545 [0.0, 1.0],
5546 [0.0, 1.0],
5547 [1.0, 2.0],
5548 [1.0, 2.0],
5549 [1.0, 2.0],
5550 ).o("pivot", "middle");
5551 let data = quiver3_data([
5552 (0.0, 0.0, 0.0, 1.0, 1.0, 1.0),
5553 (1.0, 1.0, 1.0, 2.0, 2.0, 2.0),
5554 ]).o("pivot", "middle");
5555 let triples = quiver3_triples(
5556 [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
5557 [(1.0, 1.0, 1.0), (2.0, 2.0, 2.0)],
5558 ).o("pivot", "middle");
5559 assert_eq!(norm, data);
5560 assert_eq!(norm, triples);
5561 }
5562
5563 #[test]
5564 fn test_surface() {
5565 Mpl::new_3d([])
5566 & surface(
5567 [[0.0, 1.0], [0.0, 1.0]],
5568 [[0.0, 0.0], [1.0, 1.0]],
5569 [[0.0, 1.0], [2.0, 3.0]],
5570 ).o("cmap", "rainbow")
5571 | runner()
5572 }
5573
5574 #[test]
5575 fn test_surface_data() {
5576 Mpl::new_3d([])
5577 & surface_data(
5578 [
5579 (0.0, 0.0, 0.0),
5580 (1.0, 0.0, 1.0),
5581 (0.0, 1.0, 2.0),
5582 (1.0, 1.0, 3.0),
5583 ],
5584 2,
5585 ).o("cmap", "rainbow")
5586 | runner()
5587 }
5588
5589 #[test]
5590 fn test_surface_flat() {
5591 Mpl::new_3d([])
5592 & surface_flat(
5593 [0.0, 1.0, 0.0, 1.0],
5594 [0.0, 0.0, 1.0, 1.0],
5595 [0.0, 1.0, 2.0, 3.0],
5596 2,
5597 ).o("cmap", "rainbow")
5598 | runner()
5599 }
5600
5601 #[test]
5602 fn test_surface_eq() {
5603 let norm = surface(
5604 [[0.0, 1.0], [0.0, 1.0]],
5605 [[0.0, 0.0], [1.0, 1.0]],
5606 [[0.0, 1.0], [2.0, 3.0]],
5607 ).o("cmap", "rainbow");
5608 let data = surface_data(
5609 [
5610 (0.0, 0.0, 0.0),
5611 (1.0, 0.0, 1.0),
5612 (0.0, 1.0, 2.0),
5613 (1.0, 1.0, 3.0),
5614 ],
5615 2,
5616 ).o("cmap", "rainbow");
5617 let flat = surface_flat(
5618 [0.0, 1.0, 0.0, 1.0],
5619 [0.0, 0.0, 1.0, 1.0],
5620 [0.0, 1.0, 2.0, 3.0],
5621 2,
5622 ).o("cmap", "rainbow");
5623 assert_eq!(norm, data);
5624 assert_eq!(norm, flat);
5625 }
5626
5627 #[test]
5628 fn test_trisurf() {
5629 Mpl::new_3d([])
5630 & trisurf(
5631 [0.0, 1.0, 0.0, 1.0],
5632 [0.0, 0.0, 1.0, 1.0],
5633 [0.0, 1.0, 2.0, 3.0],
5634 ).o("cmap", "rainbow")
5635 | runner()
5636 }
5637
5638 #[test]
5639 fn test_trisurf_data() {
5640 Mpl::new_3d([])
5641 & trisurf_data([
5642 (0.0, 0.0, 0.0),
5643 (1.0, 0.0, 1.0),
5644 (0.0, 1.0, 2.0),
5645 (1.0, 1.0, 3.0),
5646 ]).o("cmap", "rainbow")
5647 | runner()
5648 }
5649
5650 #[test]
5651 fn test_trisurf_eq() {
5652 let norm = trisurf(
5653 [0.0, 1.0, 0.0, 1.0],
5654 [0.0, 0.0, 1.0, 1.0],
5655 [0.0, 1.0, 2.0, 3.0],
5656 ).o("cmap", "rainbow");
5657 let data = trisurf_data([
5658 (0.0, 0.0, 0.0),
5659 (1.0, 0.0, 1.0),
5660 (0.0, 1.0, 2.0),
5661 (1.0, 1.0, 3.0),
5662 ]).o("cmap", "rainbow");
5663 assert_eq!(norm, data);
5664 }
5665
5666 #[test]
5667 fn test_view_init() {
5668 Mpl::new_3d([])
5669 & view_init(90.0, 0.0).o("roll", 45.0)
5670 | runner()
5671 }
5672
5673 #[test]
5674 fn test_zlabel() {
5675 Mpl::new_3d([])
5676 & zlabel("zlabel")
5677 | runner()
5678 }
5679
5680 #[test]
5681 fn test_zlim() {
5682 Mpl::new_3d([])
5683 & zlim(Some(-10.0), Some(15.0))
5684 | runner()
5685 }
5686
5687 #[test]
5688 fn test_zscale() {
5689 Mpl::new_3d([])
5690 & zscale(AxisScale::Log)
5691 | runner()
5692 }
5693
5694 #[test]
5695 fn test_zticklabels() {
5696 Mpl::new_3d([])
5697 & zticklabels([0.0, 1.0], ["zero", "one"]).o("minor", true)
5698 | runner()
5699 }
5700
5701 #[test]
5702 fn test_zticklabels_data() {
5703 Mpl::new_3d([])
5704 & zticklabels_data([(0.0, "zero"), (1.0, "one")]).o("minor", true)
5705 | runner()
5706 }
5707
5708 #[test]
5709 fn test_zticklabels_eq() {
5710 assert_eq!(
5711 zticklabels([0.0, 1.0], ["zero", "one"]).o("minor", true),
5712 zticklabels_data([(0.0, "zero"), (1.0, "one")]).o("minor", true),
5713 )
5714 }
5715
5716 #[test]
5717 fn test_zticks() {
5718 Mpl::new_3d([])
5719 & zticks([0.0, 1.0]).o("minor", true)
5720 | runner()
5721 }
5722}
5723