1use serde_json::Value;
22use crate::core::{
23 Matplotlib,
24 MatplotlibOpts,
25 Opt,
26 GSPos,
27 PyValue,
28 AsPy,
29};
30
31#[derive(Clone, Debug, PartialEq, Eq)]
39pub struct Raw(pub String);
40
41impl Raw {
42 pub fn new(s: &str) -> Self { Self(s.into()) }
44}
45
46pub fn raw(s: &str) -> Raw { Raw::new(s) }
48
49impl Matplotlib for Raw {
50 fn is_prelude(&self) -> bool { false }
51
52 fn data(&self) -> Option<Value> { None }
53
54 fn py_cmd(&self) -> String { self.0.clone() }
55}
56
57#[derive(Clone, Debug, PartialEq, Eq)]
65pub struct Prelude(pub String);
66
67impl Prelude {
68 pub fn new(s: &str) -> Self { Self(s.into()) }
70}
71
72pub fn prelude(s: &str) -> Prelude { Prelude::new(s) }
74
75impl Matplotlib for Prelude {
76 fn is_prelude(&self) -> bool { true }
77
78 fn data(&self) -> Option<Value> { None }
79
80 fn py_cmd(&self) -> String { self.0.clone() }
81}
82
83#[derive(Clone, Debug, PartialEq, Eq)]
93pub struct Backend(pub String);
94
95impl Backend {
96 pub fn new(backend: &str) -> Self { Self(backend.into()) }
98}
99
100pub fn backend(backend: &str) -> Backend { Backend::new(backend) }
102
103impl Matplotlib for Backend {
104 fn is_prelude(&self) -> bool { true }
105
106 fn data(&self) -> Option<Value> { None }
107
108 fn py_cmd(&self) -> String {
109 format!("matplotlib.use({})", self.0.as_py())
110 }
111}
112
113#[derive(Clone, Debug, PartialEq, Eq)]
123pub struct CloseFig(pub String);
124
125impl CloseFig {
126 pub fn new(fig: &str) -> Self { Self(fig.into()) }
128}
129
130pub fn close_fig(fig: &str) -> CloseFig { CloseFig::new(fig) }
132
133impl Matplotlib for CloseFig {
134 fn is_prelude(&self) -> bool { false }
135
136 fn data(&self) -> Option<Value> { None }
137
138 fn py_cmd(&self) -> String {
139 format!("plt.close({})", self.0)
140 }
141}
142
143#[derive(Clone, Debug, PartialEq, Default)]
157pub struct Init3D {
158 pub opts: Vec<Opt>,
160}
161
162impl Init3D {
163 pub fn new() -> Self { Self { opts: Vec::new() } }
165}
166
167impl Matplotlib for Init3D {
168 fn is_prelude(&self) -> bool { false }
169
170 fn data(&self) -> Option<Value> { None }
171
172 fn py_cmd(&self) -> String {
173 format!("\
174 fig = plt.figure()\n\
175 ax = axes3d.Axes3D(fig, auto_add_to_figure=False{}{})\n\
176 fig.add_axes(ax)",
177 if self.opts.is_empty() { "" } else { ", " },
178 self.opts.as_py(),
179 )
180 }
181}
182
183impl MatplotlibOpts for Init3D {
184 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
185 self.opts.push((key, val).into());
186 self
187 }
188}
189
190#[derive(Clone, Debug, PartialEq)]
206pub struct InitGrid {
207 pub nrows: usize,
209 pub ncols: usize,
211 pub opts: Vec<Opt>,
213}
214
215impl InitGrid {
216 pub fn new(nrows: usize, ncols: usize) -> Self {
218 Self { nrows, ncols, opts: Vec::new() }
219 }
220}
221
222pub fn init_grid(nrows: usize, ncols: usize) -> InitGrid {
224 InitGrid::new(nrows, ncols)
225}
226
227impl Matplotlib for InitGrid {
228 fn is_prelude(&self) -> bool { false }
229
230 fn data(&self) -> Option<Value> { None }
231
232 fn py_cmd(&self) -> String {
233 format!("\
234 fig, AX = plt.subplots(nrows={}, ncols={}{}{})\n\
235 AX = AX.reshape(({}, {}))\n\
236 ax = AX[0, 0]",
237 self.nrows,
238 self.ncols,
239 if self.opts.is_empty() { "" } else { ", " },
240 self.opts.as_py(),
241 self.nrows,
242 self.ncols,
243 )
244 }
245}
246
247impl MatplotlibOpts for InitGrid {
248 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
249 self.opts.push((key, val).into());
250 self
251 }
252}
253
254#[derive(Clone, Debug, PartialEq)]
276pub struct InitGridSpec {
277 pub gridspec_kw: Vec<Opt>,
279 pub positions: Vec<GSPos>,
281}
282
283impl InitGridSpec {
284 pub fn new<I, P>(gridspec_kw: I, positions: P) -> Self
286 where
287 I: IntoIterator<Item = Opt>,
288 P: IntoIterator<Item = GSPos>,
289 {
290 Self {
291 gridspec_kw: gridspec_kw.into_iter().collect(),
292 positions: positions.into_iter().collect(),
293 }
294 }
295}
296
297pub fn init_gridspec<I, P>(gridspec_kw: I, positions: P) -> InitGridSpec
299where
300 I: IntoIterator<Item = Opt>,
301 P: IntoIterator<Item = GSPos>,
302{
303 InitGridSpec::new(gridspec_kw, positions)
304}
305
306impl Matplotlib for InitGridSpec {
307 fn is_prelude(&self) -> bool { false }
308
309 fn data(&self) -> Option<Value> { None }
310
311 fn py_cmd(&self) -> String {
312 let mut code =
313 format!("\
314 fig = plt.figure()\n\
315 gs = fig.add_gridspec({})\n\
316 AX = np.array([\n",
317 self.gridspec_kw.as_py(),
318 );
319 for GSPos { i, j, sharex: _, sharey: _ } in self.positions.iter() {
320 code.push_str(
321 &format!(" fig.add_subplot(gs[{}:{}, {}:{}]),\n",
322 i.start, i.end, j.start, j.end,
323 )
324 );
325 }
326 code.push_str("])\n");
327 let iter = self.positions.iter().enumerate();
328 for (k, GSPos { i: _, j: _, sharex, sharey }) in iter {
329 if let Some(x) = sharex {
330 code.push_str(&format!("AX[{}].sharex(AX[{}])\n", k, x));
331 }
332 if let Some(y) = sharey {
333 code.push_str(&format!("AX[{}].sharey(AX[{}])\n", k, y));
334 }
335 }
336 code.push_str("ax = AX[0]\n");
337 code
338 }
339}
340
341impl MatplotlibOpts for InitGridSpec {
342 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
343 self.gridspec_kw.push((key, val).into());
344 self
345 }
346}
347
348#[derive(Clone, Debug, PartialEq)]
362pub struct RcParam {
363 pub key: String,
365 pub val: PyValue,
367}
368
369impl RcParam {
370 pub fn new<T: Into<PyValue>>(key: &str, val: T) -> Self {
372 Self { key: key.into(), val: val.into() }
373 }
374}
375
376pub fn rcparam<T: Into<PyValue>>(key: &str, val: T) -> RcParam {
378 RcParam::new(key, val)
379}
380
381impl Matplotlib for RcParam {
382 fn is_prelude(&self) -> bool { true }
383
384 fn data(&self) -> Option<Value> { None }
385
386 fn py_cmd(&self) -> String {
387 format!("plt.rcParams[{}] = {}", self.key.as_py(), self.val.as_py())
388 }
389}
390
391#[derive(Copy, Clone, Debug, PartialEq, Eq)]
401pub struct TeX(pub bool);
402
403impl TeX {
404 pub fn on() -> Self { Self(true) }
406
407 pub fn off() -> Self { Self(false) }
409}
410
411pub fn tex_on() -> TeX { TeX(true) }
413
414pub fn tex_off() -> TeX { TeX(false) }
416
417impl Matplotlib for TeX {
418 fn is_prelude(&self) -> bool { true }
419
420 fn data(&self) -> Option<Value> { None }
421
422 fn py_cmd(&self) -> String {
423 format!("plt.rcParams[\"text.usetex\"] = {}", self.0.as_py())
424 }
425}
426
427#[derive(Clone, Debug, PartialEq, Eq)]
437pub struct FocusAx(pub String);
438
439impl FocusAx {
440 pub fn new(expr: &str) -> Self { Self(expr.into()) }
442}
443
444pub fn focus_ax(expr: &str) -> FocusAx { FocusAx::new(expr) }
446
447impl Matplotlib for FocusAx {
448 fn is_prelude(&self) -> bool { false }
449
450 fn data(&self) -> Option<Value> { None }
451
452 fn py_cmd(&self) -> String { format!("ax = {}", self.0) }
453}
454
455#[derive(Clone, Debug, PartialEq, Eq)]
465pub struct FocusFig(pub String);
466
467impl FocusFig {
468 pub fn new(expr: &str) -> Self { Self(expr.into()) }
470}
471
472pub fn focus_fig(expr: &str) -> FocusFig { FocusFig::new(expr) }
474
475impl Matplotlib for FocusFig {
476 fn is_prelude(&self) -> bool { false }
477
478 fn data(&self) -> Option<Value> { None }
479
480 fn py_cmd(&self) -> String { format!("fig = {}", self.0) }
481}
482
483#[derive(Clone, Debug, PartialEq, Eq)]
493pub struct FocusCBar(pub String);
494
495impl FocusCBar {
496 pub fn new(expr: &str) -> Self { Self(expr.into()) }
498}
499
500pub fn focus_cbar(expr: &str) -> FocusCBar { FocusCBar::new(expr) }
502
503impl Matplotlib for FocusCBar {
504 fn is_prelude(&self) -> bool { false }
505
506 fn data(&self) -> Option<Value> { None }
507
508 fn py_cmd(&self) -> String { format!("cbar = {}", self.0) }
509}
510
511#[derive(Clone, Debug, PartialEq, Eq)]
521pub struct FocusIm(pub String);
522
523impl FocusIm {
524 pub fn new(expr: &str) -> Self { Self(expr.into()) }
526}
527
528pub fn focus_im(expr: &str) -> FocusIm { FocusIm::new(expr) }
530
531impl Matplotlib for FocusIm {
532 fn is_prelude(&self) -> bool { false }
533
534 fn data(&self) -> Option<Value> { None }
535
536 fn py_cmd(&self) -> String { format!("im = {}", self.0) }
537}
538
539#[derive(Clone, Debug, PartialEq)]
549pub struct Plot {
550 pub x: Vec<f64>,
552 pub y: Vec<f64>,
554 pub opts: Vec<Opt>,
556}
557
558impl Plot {
559 pub fn new<X, Y>(x: X, y: Y) -> Self
561 where
562 X: IntoIterator<Item = f64>,
563 Y: IntoIterator<Item = f64>,
564 {
565 Self {
566 x: x.into_iter().collect(),
567 y: y.into_iter().collect(),
568 opts: Vec::new(),
569 }
570 }
571
572 pub fn new_pairs<I>(data: I) -> Self
574 where I: IntoIterator<Item = (f64, f64)>
575 {
576 let (x, y): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
577 Self { x, y, opts: Vec::new() }
578 }
579}
580
581pub fn plot<X, Y>(x: X, y: Y) -> Plot
583where
584 X: IntoIterator<Item = f64>,
585 Y: IntoIterator<Item = f64>,
586{
587 Plot::new(x, y)
588}
589
590pub fn plot_pairs<I>(data: I) -> Plot
592where I: IntoIterator<Item = (f64, f64)>
593{
594 Plot::new_pairs(data)
595}
596
597impl Matplotlib for Plot {
598 fn is_prelude(&self) -> bool { false }
599
600 fn data(&self) -> Option<Value> {
601 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
602 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
603 Some(Value::Array(vec![x.into(), y.into()]))
604 }
605
606 fn py_cmd(&self) -> String {
607 format!("ax.plot(data[0], data[1]{}{})",
608 if self.opts.is_empty() { "" } else { ", " },
609 self.opts.as_py(),
610 )
611 }
612}
613
614impl MatplotlibOpts for Plot {
615 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
616 self.opts.push((key, val).into());
617 self
618 }
619}
620
621#[derive(Clone, Debug, PartialEq)]
631pub struct Hist {
632 pub data: Vec<f64>,
634 pub opts: Vec<Opt>,
636}
637
638impl Hist {
639 pub fn new<I>(data: I) -> Self
641 where I: IntoIterator<Item = f64>
642 {
643 let data: Vec<f64> = data.into_iter().collect();
644 Self { data, opts: Vec::new() }
645 }
646}
647
648pub fn hist<I>(data: I) -> Hist
650where I: IntoIterator<Item = f64>
651{
652 Hist::new(data)
653}
654
655impl Matplotlib for Hist {
656 fn is_prelude(&self) -> bool { false }
657
658 fn data(&self) -> Option<Value> {
659 let data: Vec<Value> =
660 self.data.iter().copied().map(Value::from).collect();
661 Some(Value::Array(data))
662 }
663
664 fn py_cmd(&self) -> String {
665 format!("ax.hist(data{}{})",
666 if self.opts.is_empty() { "" } else { ", " },
667 self.opts.as_py(),
668 )
669 }
670}
671
672impl MatplotlibOpts for Hist {
673 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
674 self.opts.push((key, val).into());
675 self
676 }
677}
678
679#[derive(Clone, Debug, PartialEq)]
689pub struct Hist2d {
690 pub x: Vec<f64>,
692 pub y: Vec<f64>,
694 pub opts: Vec<Opt>,
696}
697
698impl Hist2d {
699 pub fn new<X, Y>(x: X, y: Y) -> Self
701 where
702 X: IntoIterator<Item = f64>,
703 Y: IntoIterator<Item = f64>,
704 {
705 let x: Vec<f64> = x.into_iter().collect();
706 let y: Vec<f64> = y.into_iter().collect();
707 Self { x, y, opts: Vec::new() }
708 }
709
710 pub fn new_pairs<I>(data: I) -> Self
712 where I: IntoIterator<Item = (f64, f64)>
713 {
714 let (x, y): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
715 Self { x, y, opts: Vec::new() }
716 }
717}
718
719pub fn hist2d<X, Y>(x: X, y: Y) -> Hist2d
721where
722 X: IntoIterator<Item = f64>,
723 Y: IntoIterator<Item = f64>,
724{
725 Hist2d::new(x, y)
726}
727
728pub fn hist2d_pairs<I>(data: I) -> Hist2d
730where I: IntoIterator<Item = (f64, f64)>
731{
732 Hist2d::new_pairs(data)
733}
734
735impl Matplotlib for Hist2d {
736 fn is_prelude(&self) -> bool { false }
737
738 fn data(&self) -> Option<Value> {
739 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
740 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
741 Some(Value::Array(vec![x.into(), y.into()]))
742 }
743
744 fn py_cmd(&self) -> String {
745 format!("ax.hist2d(data[0], data[1]{}{})",
746 if self.opts.is_empty() { "" } else { ", " },
747 self.opts.as_py(),
748 )
749 }
750}
751
752impl MatplotlibOpts for Hist2d {
753 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
754 self.opts.push((key, val).into());
755 self
756 }
757}
758
759#[derive(Clone, Debug, PartialEq)]
769pub struct Scatter {
770 pub x: Vec<f64>,
772 pub y: Vec<f64>,
774 pub opts: Vec<Opt>,
776}
777
778impl Scatter {
779 pub fn new<X, Y>(x: X, y: Y) -> Self
781 where
782 X: IntoIterator<Item = f64>,
783 Y: IntoIterator<Item = f64>,
784 {
785 Self {
786 x: x.into_iter().collect(),
787 y: y.into_iter().collect(),
788 opts: Vec::new(),
789 }
790 }
791
792 pub fn new_pairs<I>(data: I) -> Self
794 where I: IntoIterator<Item = (f64, f64)>
795 {
796 let (x, y): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
797 Self { x, y, opts: Vec::new() }
798 }
799}
800
801pub fn scatter<X, Y>(x: X, y: Y) -> Scatter
803where
804 X: IntoIterator<Item = f64>,
805 Y: IntoIterator<Item = f64>,
806{
807 Scatter::new(x, y)
808}
809
810pub fn scatter_pairs<I>(data: I) -> Scatter
812where I: IntoIterator<Item = (f64, f64)>
813{
814 Scatter::new_pairs(data)
815}
816
817impl Matplotlib for Scatter {
818 fn is_prelude(&self) -> bool { false }
819
820 fn data(&self) -> Option<Value> {
821 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
822 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
823 Some(Value::Array(vec![x.into(), y.into()]))
824 }
825
826 fn py_cmd(&self) -> String {
827 format!("ax.scatter(data[0], data[1]{}{})",
828 if self.opts.is_empty() { "" } else { ", " },
829 self.opts.as_py(),
830 )
831 }
832}
833
834impl MatplotlibOpts for Scatter {
835 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
836 self.opts.push((key, val).into());
837 self
838 }
839}
840
841#[derive(Clone, Debug, PartialEq)]
851pub struct Stem {
852 pub x: Vec<f64>,
854 pub y: Vec<f64>,
856 pub opts: Vec<Opt>,
858}
859
860impl Stem {
861 pub fn new<X, Y>(x: X, y: Y) -> Self
863 where
864 X: IntoIterator<Item = f64>,
865 Y: IntoIterator<Item = f64>,
866 {
867 Self {
868 x: x.into_iter().collect(),
869 y: y.into_iter().collect(),
870 opts: Vec::new(),
871 }
872 }
873
874 pub fn new_pairs<I>(data: I) -> Self
876 where I: IntoIterator<Item = (f64, f64)>
877 {
878 let (x, y): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
879 Self { x, y, opts: Vec::new() }
880 }
881}
882
883pub fn stem<X, Y>(x: X, y: Y) -> Stem
885where
886 X: IntoIterator<Item = f64>,
887 Y: IntoIterator<Item = f64>,
888{
889 Stem::new(x, y)
890}
891
892pub fn stem_pairs<I>(data: I) -> Stem
894where I: IntoIterator<Item = (f64, f64)>
895{
896 Stem::new_pairs(data)
897}
898
899impl Matplotlib for Stem {
900 fn is_prelude(&self) -> bool { false }
901
902 fn data(&self) -> Option<Value> {
903 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
904 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
905 Some(Value::Array(vec![x.into(), y.into()]))
906 }
907
908 fn py_cmd(&self) -> String {
909 format!("ax.stem(data[0], data[1]{}{})",
910 if self.opts.is_empty() { "" } else { ", " },
911 self.opts.as_py(),
912 )
913 }
914}
915
916impl MatplotlibOpts for Stem {
917 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
918 self.opts.push((key, val).into());
919 self
920 }
921}
922
923#[derive(Clone, Debug, PartialEq)]
933pub struct Stairs {
934 pub x: Vec<f64>,
936 pub y: Vec<f64>,
938 pub opts: Vec<Opt>,
940}
941
942impl Stairs {
943 pub fn new<X, Y>(x: X, y: Y) -> Self
945 where
946 X: IntoIterator<Item = f64>,
947 Y: IntoIterator<Item = f64>,
948 {
949 Self {
950 x: x.into_iter().collect(),
951 y: y.into_iter().collect(),
952 opts: Vec::new(),
953 }
954 }
955
956 pub fn new_pairs<I>(data: I) -> Self
958 where I: IntoIterator<Item = (f64, f64)>
959 {
960 let (x, y): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
961 Self { x, y, opts: Vec::new() }
962 }
963}
964
965pub fn stairs<X, Y>(x: X, y: Y) -> Stairs
967where
968 X: IntoIterator<Item = f64>,
969 Y: IntoIterator<Item = f64>,
970{
971 Stairs::new(x, y)
972}
973
974pub fn stairs_pairs<I>(data: I) -> Stairs
976where I: IntoIterator<Item = (f64, f64)>
977{
978 Stairs::new_pairs(data)
979}
980
981impl Matplotlib for Stairs {
982 fn is_prelude(&self) -> bool { false }
983
984 fn data(&self) -> Option<Value> {
985 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
986 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
987 Some(Value::Array(vec![x.into(), y.into()]))
988 }
989
990 fn py_cmd(&self) -> String {
991 format!("ax.stairs(data[1], data[0]{}{})",
992 if self.opts.is_empty() { "" } else { ", " },
993 self.opts.as_py(),
994 )
995 }
996}
997
998impl MatplotlibOpts for Stairs {
999 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1000 self.opts.push((key, val).into());
1001 self
1002 }
1003}
1004
1005#[derive(Clone, Debug, PartialEq)]
1015pub struct Step {
1016 pub x: Vec<f64>,
1018 pub y: Vec<f64>,
1020 pub opts: Vec<Opt>,
1022}
1023
1024impl Step {
1025 pub fn new<X, Y>(x: X, y: Y) -> Self
1027 where
1028 X: IntoIterator<Item = f64>,
1029 Y: IntoIterator<Item = f64>,
1030 {
1031 Self {
1032 x: x.into_iter().collect(),
1033 y: y.into_iter().collect(),
1034 opts: Vec::new(),
1035 }
1036 }
1037
1038 pub fn new_pairs<I>(data: I) -> Self
1040 where I: IntoIterator<Item = (f64, f64)>
1041 {
1042 let (x, y): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
1043 Self { x, y, opts: Vec::new() }
1044 }
1045}
1046
1047pub fn step<X, Y>(x: X, y: Y) -> Step
1049where
1050 X: IntoIterator<Item = f64>,
1051 Y: IntoIterator<Item = f64>,
1052{
1053 Step::new(x, y)
1054}
1055
1056pub fn step_pairs<I>(data: I) -> Step
1058where I: IntoIterator<Item = (f64, f64)>
1059{
1060 Step::new_pairs(data)
1061}
1062
1063impl Matplotlib for Step {
1064 fn is_prelude(&self) -> bool { false }
1065
1066 fn data(&self) -> Option<Value> {
1067 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1068 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1069 Some(Value::Array(vec![x.into(), y.into()]))
1070 }
1071
1072 fn py_cmd(&self) -> String {
1073 format!("ax.step(data[0], data[1]{}{})",
1074 if self.opts.is_empty() { "" } else { ", " },
1075 self.opts.as_py(),
1076 )
1077 }
1078}
1079
1080impl MatplotlibOpts for Step {
1081 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1082 self.opts.push((key, val).into());
1083 self
1084 }
1085}
1086
1087#[derive(Clone, Debug, PartialEq)]
1097pub struct Quiver {
1098 pub x: Vec<f64>,
1100 pub y: Vec<f64>,
1102 pub vx: Vec<f64>,
1104 pub vy: Vec<f64>,
1106 pub opts: Vec<Opt>,
1108}
1109
1110impl Quiver {
1111 pub fn new<X, Y, VX, VY>(x: X, y: Y, vx: VX, vy: VY) -> Self
1113 where
1114 X: IntoIterator<Item = f64>,
1115 Y: IntoIterator<Item = f64>,
1116 VX: IntoIterator<Item = f64>,
1117 VY: IntoIterator<Item = f64>,
1118 {
1119 Self {
1120 x: x.into_iter().collect(),
1121 y: y.into_iter().collect(),
1122 vx: vx.into_iter().collect(),
1123 vy: vy.into_iter().collect(),
1124 opts: Vec::new(),
1125 }
1126 }
1127
1128 pub fn new_pairs<I, VI>(xy: I, vxy: VI) -> Self
1131 where
1132 I: IntoIterator<Item = (f64, f64)>,
1133 VI: IntoIterator<Item = (f64, f64)>,
1134 {
1135 let (x, y) = xy.into_iter().unzip();
1136 let (vx, vy) = vxy.into_iter().unzip();
1137 Self { x, y, vx, vy, opts: Vec::new() }
1138 }
1139
1140 pub fn new_data<I>(data: I) -> Self
1144 where I: IntoIterator<Item = (f64, f64, f64, f64)>
1145 {
1146 let (((x, y), vx), vy) = data.into_iter().map(assoc).unzip();
1147 Self { x, y, vx, vy, opts: Vec::new() }
1148 }
1149}
1150
1151pub fn quiver<X, Y, VX, VY>(x: X, y: Y, vx: VX, vy: VY) -> Quiver
1153where
1154 X: IntoIterator<Item = f64>,
1155 Y: IntoIterator<Item = f64>,
1156 VX: IntoIterator<Item = f64>,
1157 VY: IntoIterator<Item = f64>,
1158{
1159 Quiver::new(x, y, vx, vy)
1160}
1161
1162pub fn quiver_pairs<I, VI>(xy: I, vxy: VI) -> Quiver
1165where
1166 I: IntoIterator<Item = (f64, f64)>,
1167 VI: IntoIterator<Item = (f64, f64)>,
1168{
1169 Quiver::new_pairs(xy, vxy)
1170}
1171
1172pub fn quiver_data<I>(data: I) -> Quiver
1176where I: IntoIterator<Item = (f64, f64, f64, f64)>
1177{
1178 Quiver::new_data(data)
1179}
1180
1181impl Matplotlib for Quiver {
1182 fn is_prelude(&self) -> bool { false }
1183
1184 fn data(&self) -> Option<Value> {
1185 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1186 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1187 let vx: Vec<Value> = self.vx.iter().copied().map(Value::from).collect();
1188 let vy: Vec<Value> = self.vy.iter().copied().map(Value::from).collect();
1189 Some(Value::Array(vec![x.into(), y.into(), vx.into(), vy.into()]))
1190 }
1191
1192 fn py_cmd(&self) -> String {
1193 format!("ax.quiver(data[0], data[1], data[2], data[3]{}{})",
1194 if self.opts.is_empty() { "" } else { ", " },
1195 self.opts.as_py(),
1196 )
1197 }
1198}
1199
1200impl MatplotlibOpts for Quiver {
1201 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1202 self.opts.push((key, val).into());
1203 self
1204 }
1205}
1206
1207#[derive(Clone, Debug, PartialEq)]
1217pub struct Bar {
1218 pub x: Vec<f64>,
1220 pub y: Vec<f64>,
1222 pub opts: Vec<Opt>,
1224}
1225
1226impl Bar {
1227 pub fn new<X, Y>(x: X, y: Y) -> Self
1229 where
1230 X: IntoIterator<Item = f64>,
1231 Y: IntoIterator<Item = f64>,
1232 {
1233 Self {
1234 x: x.into_iter().collect(),
1235 y: y.into_iter().collect(),
1236 opts: Vec::new(),
1237 }
1238 }
1239
1240 pub fn new_pairs<I>(data: I) -> Self
1242 where I: IntoIterator<Item = (f64, f64)>
1243 {
1244 let (x, y): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
1245 Self { x, y, opts: Vec::new() }
1246 }
1247}
1248
1249pub fn bar<X, Y>(x: X, y: Y) -> Bar
1251where
1252 X: IntoIterator<Item = f64>,
1253 Y: IntoIterator<Item = f64>,
1254{
1255 Bar::new(x, y)
1256}
1257
1258pub fn bar_pairs<I>(data: I) -> Bar
1260where I: IntoIterator<Item = (f64, f64)>
1261{
1262 Bar::new_pairs(data)
1263}
1264
1265impl Matplotlib for Bar {
1266 fn is_prelude(&self) -> bool { false }
1267
1268 fn data(&self) -> Option<Value> {
1269 let x: Vec<Value> =
1270 self.x.iter().copied().map(Value::from).collect();
1271 let y: Vec<Value> =
1272 self.y.iter().copied().map(Value::from).collect();
1273 Some(Value::Array(vec![x.into(), y.into()]))
1274 }
1275
1276 fn py_cmd(&self) -> String {
1277 format!("ax.bar(data[0], data[1]{}{})",
1278 if self.opts.is_empty() { "" } else { ", " },
1279 self.opts.as_py(),
1280 )
1281 }
1282}
1283
1284impl MatplotlibOpts for Bar {
1285 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1286 self.opts.push((key, val).into());
1287 self
1288 }
1289}
1290
1291#[derive(Clone, Debug, PartialEq)]
1301pub struct BarH {
1302 pub y: Vec<f64>,
1304 pub w: Vec<f64>,
1306 pub opts: Vec<Opt>,
1308}
1309
1310impl BarH {
1311 pub fn new<Y, W>(y: Y, w: W) -> Self
1313 where
1314 Y: IntoIterator<Item = f64>,
1315 W: IntoIterator<Item = f64>,
1316 {
1317 Self {
1318 y: y.into_iter().collect(),
1319 w: w.into_iter().collect(),
1320 opts: Vec::new(),
1321 }
1322 }
1323
1324 pub fn new_pairs<I>(data: I) -> Self
1326 where I: IntoIterator<Item = (f64, f64)>
1327 {
1328 let (y, w): (Vec<f64>, Vec<f64>) = data.into_iter().unzip();
1329 Self { y, w, opts: Vec::new() }
1330 }
1331}
1332
1333pub fn barh<Y, W>(y: Y, w: W) -> BarH
1335where
1336 Y: IntoIterator<Item = f64>,
1337 W: IntoIterator<Item = f64>,
1338{
1339 BarH::new(y, w)
1340}
1341
1342pub fn barh_pairs<I>(data: I) -> BarH
1344where I: IntoIterator<Item = (f64, f64)>
1345{
1346 BarH::new_pairs(data)
1347}
1348
1349impl Matplotlib for BarH {
1350 fn is_prelude(&self) -> bool { false }
1351
1352 fn data(&self) -> Option<Value> {
1353 let y: Vec<Value> =
1354 self.y.iter().copied().map(Value::from).collect();
1355 let w: Vec<Value> =
1356 self.w.iter().copied().map(Value::from).collect();
1357 Some(Value::Array(vec![y.into(), w.into()]))
1358 }
1359
1360 fn py_cmd(&self) -> String {
1361 format!("ax.barh(data[0], data[1]{}{})",
1362 if self.opts.is_empty() { "" } else { ", " },
1363 self.opts.as_py(),
1364 )
1365 }
1366}
1367
1368impl MatplotlibOpts for BarH {
1369 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1370 self.opts.push((key, val).into());
1371 self
1372 }
1373}
1374
1375#[derive(Clone, Debug, PartialEq)]
1385pub struct Errorbar {
1386 pub x: Vec<f64>,
1388 pub y: Vec<f64>,
1390 pub e: Vec<f64>,
1392 pub opts: Vec<Opt>,
1394}
1395
1396impl Errorbar {
1397 pub fn new<X, Y, E>(x: X, y: Y, e: E) -> Self
1399 where
1400 X: IntoIterator<Item = f64>,
1401 Y: IntoIterator<Item = f64>,
1402 E: IntoIterator<Item = f64>,
1403 {
1404 Self {
1405 x: x.into_iter().collect(),
1406 y: y.into_iter().collect(),
1407 e: e.into_iter().collect(),
1408 opts: Vec::new(),
1409 }
1410 }
1411
1412 pub fn new_data<I>(data: I) -> Self
1414 where I: IntoIterator<Item = (f64, f64, f64)>
1415 {
1416 let ((x, y), e) = data.into_iter().map(assoc).unzip();
1417 Self { x, y, e, opts: Vec::new() }
1418 }
1419}
1420
1421pub fn errorbar<X, Y, E>(x: X, y: Y, e: E) -> Errorbar
1423where
1424 X: IntoIterator<Item = f64>,
1425 Y: IntoIterator<Item = f64>,
1426 E: IntoIterator<Item = f64>,
1427{
1428 Errorbar::new(x, y, e)
1429}
1430
1431pub fn errorbar_data<I>(data: I) -> Errorbar
1433where I: IntoIterator<Item = (f64, f64, f64)>
1434{
1435 Errorbar::new_data(data)
1436}
1437
1438impl Matplotlib for Errorbar {
1439 fn is_prelude(&self) -> bool { false }
1440
1441 fn data(&self) -> Option<Value> {
1442 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1443 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1444 let e: Vec<Value> = self.e.iter().copied().map(Value::from).collect();
1445 Some(Value::Array(vec![x.into(), y.into(), e.into()]))
1446 }
1447
1448 fn py_cmd(&self) -> String {
1449 format!("ax.errorbar(data[0], data[1], data[2]{}{})",
1450 if self.opts.is_empty() { "" } else { ", " },
1451 self.opts.as_py(),
1452 )
1453 }
1454}
1455
1456impl MatplotlibOpts for Errorbar {
1457 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1458 self.opts.push((key, val).into());
1459 self
1460 }
1461}
1462
1463impl From<FillBetween> for Errorbar {
1465 fn from(fill_between: FillBetween) -> Self {
1466 let FillBetween { x, mut y1, mut y2, opts } = fill_between;
1467 y1.iter_mut()
1468 .zip(y2.iter_mut())
1469 .for_each(|(y1k, y2k)| {
1470 let y1 = *y1k;
1471 let y2 = *y2k;
1472 *y1k = 0.5 * (y1 + y2);
1473 *y2k = 0.5 * (y1 - y2).abs();
1474 });
1475 Self { x, y: y1, e: y2, opts }
1476 }
1477}
1478
1479#[derive(Clone, Debug, PartialEq)]
1489pub struct Errorbar2 {
1490 pub x: Vec<f64>,
1492 pub y: Vec<f64>,
1494 pub e_neg: Vec<f64>,
1496 pub e_pos: Vec<f64>,
1498 pub opts: Vec<Opt>,
1500}
1501
1502impl Errorbar2 {
1503 pub fn new<X, Y, E1, E2>(x: X, y: Y, e_neg: E1, e_pos: E2) -> Self
1505 where
1506 X: IntoIterator<Item = f64>,
1507 Y: IntoIterator<Item = f64>,
1508 E1: IntoIterator<Item = f64>,
1509 E2: IntoIterator<Item = f64>,
1510 {
1511 Self {
1512 x: x.into_iter().collect(),
1513 y: y.into_iter().collect(),
1514 e_neg: e_neg.into_iter().collect(),
1515 e_pos: e_pos.into_iter().collect(),
1516 opts: Vec::new(),
1517 }
1518 }
1519
1520 pub fn new_data<I>(data: I) -> Self
1522 where I: IntoIterator<Item = (f64, f64, f64, f64)>
1523 {
1524 let (((x, y), e_neg), e_pos) =
1525 data.into_iter().map(assoc).unzip();
1526 Self { x, y, e_neg, e_pos, opts: Vec::new() }
1527 }
1528}
1529
1530pub fn errorbar2<X, Y, E1, E2>(x: X, y: Y, e_neg: E1, e_pos: E2) -> Errorbar2
1532where
1533 X: IntoIterator<Item = f64>,
1534 Y: IntoIterator<Item = f64>,
1535 E1: IntoIterator<Item = f64>,
1536 E2: IntoIterator<Item = f64>,
1537{
1538 Errorbar2::new(x, y, e_neg, e_pos)
1539}
1540
1541pub fn errorbar2_data<I>(data: I) -> Errorbar2
1543where I: IntoIterator<Item = (f64, f64, f64, f64)>
1544{
1545 Errorbar2::new_data(data)
1546}
1547
1548impl Matplotlib for Errorbar2 {
1549 fn is_prelude(&self) -> bool { false }
1550
1551 fn data(&self) -> Option<Value> {
1552 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1553 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1554 let e_neg: Vec<Value> =
1555 self.e_neg.iter().copied().map(Value::from).collect();
1556 let e_pos: Vec<Value> =
1557 self.e_pos.iter().copied().map(Value::from).collect();
1558 Some(Value::Array(
1559 vec![x.into(), y.into(), e_neg.into(), e_pos.into()]))
1560 }
1561
1562 fn py_cmd(&self) -> String {
1563 format!("ax.errorbar(data[0], data[1], [data[2], data[3]]{}{})",
1564 if self.opts.is_empty() { "" } else { ", " },
1565 self.opts.as_py(),
1566 )
1567 }
1568}
1569
1570impl MatplotlibOpts for Errorbar2 {
1571 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1572 self.opts.push((key, val).into());
1573 self
1574 }
1575}
1576
1577struct Chunks<I, T>
1578where I: Iterator<Item = T>
1579{
1580 chunksize: usize,
1581 buflen: usize,
1582 buf: Vec<T>,
1583 iter: I,
1584}
1585
1586impl<I, T> Chunks<I, T>
1587where I: Iterator<Item = T>
1588{
1589 fn new(iter: I, chunksize: usize) -> Self {
1590 if chunksize == 0 { panic!("chunk size cannot be zero"); }
1591 Self {
1592 chunksize,
1593 buflen: 0,
1594 buf: Vec::with_capacity(chunksize),
1595 iter,
1596 }
1597 }
1598}
1599
1600impl<I, T> Iterator for Chunks<I, T>
1601where I: Iterator<Item = T>
1602{
1603 type Item = Vec<T>;
1604
1605 fn next(&mut self) -> Option<Self::Item> {
1606 loop {
1607 if let Some(item) = self.iter.next() {
1608 self.buf.push(item);
1609 self.buflen += 1;
1610 if self.buflen == self.chunksize {
1611 let mut bufswap = Vec::with_capacity(self.chunksize);
1612 std::mem::swap(&mut bufswap, &mut self.buf);
1613 self.buflen = 0;
1614 return Some(bufswap);
1615 } else {
1616 continue;
1617 }
1618 } else if self.buflen > 0 {
1619 let mut bufswap = Vec::with_capacity(0);
1620 std::mem::swap(&mut bufswap, &mut self.buf);
1621 self.buflen = 0;
1622 return Some(bufswap);
1623 } else {
1624 return None;
1625 }
1626 }
1627 }
1628}
1629
1630
1631#[derive(Clone, Debug, PartialEq)]
1641pub struct Boxplot {
1642 pub data: Vec<Vec<f64>>,
1644 pub opts: Vec<Opt>,
1646}
1647
1648impl Boxplot {
1649 pub fn new<I, J>(data: I) -> Self
1651 where
1652 I: IntoIterator<Item = J>,
1653 J: IntoIterator<Item = f64>,
1654 {
1655 let data: Vec<Vec<f64>> =
1656 data.into_iter()
1657 .map(|row| row.into_iter().collect())
1658 .collect();
1659 Self { data, opts: Vec::new() }
1660 }
1661
1662 pub fn new_flat<I>(data: I, size: usize) -> Self
1670 where I: IntoIterator<Item = f64>
1671 {
1672 if size == 0 { panic!("data set size cannot be zero"); }
1673 let data: Vec<Vec<f64>> =
1674 Chunks::new(data.into_iter(), size)
1675 .collect();
1676 Self { data, opts: Vec::new() }
1677 }
1678}
1679
1680pub fn boxplot<I, J>(data: I) -> Boxplot
1682where
1683 I: IntoIterator<Item = J>,
1684 J: IntoIterator<Item = f64>,
1685{
1686 Boxplot::new(data)
1687}
1688
1689pub fn boxplot_flat<I>(data: I, size: usize) -> Boxplot
1697where I: IntoIterator<Item = f64>
1698{
1699 Boxplot::new_flat(data, size)
1700}
1701
1702impl Matplotlib for Boxplot {
1703 fn is_prelude(&self) -> bool { false }
1704
1705 fn data(&self) -> Option<Value> {
1706 let data: Vec<Value> =
1707 self.data.iter()
1708 .map(|row| {
1709 let row: Vec<Value> =
1710 row.iter().copied().map(Value::from).collect();
1711 Value::Array(row)
1712 })
1713 .collect();
1714 Some(Value::Array(data))
1715 }
1716
1717 fn py_cmd(&self) -> String {
1718 format!("ax.boxplot(data{}{})",
1719 if self.opts.is_empty() { "" } else { ", " },
1720 self.opts.as_py(),
1721 )
1722 }
1723}
1724
1725impl MatplotlibOpts for Boxplot {
1726 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1727 self.opts.push((key, val).into());
1728 self
1729 }
1730}
1731
1732#[derive(Clone, Debug, PartialEq)]
1742pub struct Violinplot {
1743 pub data: Vec<Vec<f64>>,
1745 pub opts: Vec<Opt>,
1747}
1748
1749impl Violinplot {
1750 pub fn new<I, J>(data: I) -> Self
1752 where
1753 I: IntoIterator<Item = J>,
1754 J: IntoIterator<Item = f64>,
1755 {
1756 let data: Vec<Vec<f64>> =
1757 data.into_iter()
1758 .map(|row| row.into_iter().collect())
1759 .collect();
1760 Self { data, opts: Vec::new() }
1761 }
1762
1763 pub fn new_flat<I>(data: I, size: usize) -> Self
1771 where I: IntoIterator<Item = f64>
1772 {
1773 if size == 0 { panic!("data set size cannot be zero"); }
1774 let data: Vec<Vec<f64>> =
1775 Chunks::new(data.into_iter(), size)
1776 .collect();
1777 Self { data, opts: Vec::new() }
1778 }
1779}
1780
1781pub fn violinplot<I, J>(data: I) -> Violinplot
1783where
1784 I: IntoIterator<Item = J>,
1785 J: IntoIterator<Item = f64>,
1786{
1787 Violinplot::new(data)
1788}
1789
1790pub fn violinplot_flat<I>(data: I, size: usize) -> Violinplot
1798where I: IntoIterator<Item = f64>
1799{
1800 Violinplot::new_flat(data, size)
1801}
1802
1803impl Matplotlib for Violinplot {
1804 fn is_prelude(&self) -> bool { false }
1805
1806 fn data(&self) -> Option<Value> {
1807 let data: Vec<Value> =
1808 self.data.iter()
1809 .map(|row| {
1810 let row: Vec<Value> =
1811 row.iter().copied().map(Value::from).collect();
1812 Value::Array(row)
1813 })
1814 .collect();
1815 Some(Value::Array(data))
1816 }
1817
1818 fn py_cmd(&self) -> String {
1819 format!("ax.violinplot(data{}{})",
1820 if self.opts.is_empty() { "" } else { ", " },
1821 self.opts.as_py(),
1822 )
1823 }
1824}
1825
1826impl MatplotlibOpts for Violinplot {
1827 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1828 self.opts.push((key, val).into());
1829 self
1830 }
1831}
1832
1833#[derive(Clone, Debug, PartialEq)]
1848pub struct Contour {
1849 pub x: Vec<f64>,
1851 pub y: Vec<f64>,
1853 pub z: Vec<Vec<f64>>,
1857 pub opts: Vec<Opt>,
1859}
1860
1861impl Contour {
1862 pub fn new<X, Y, ZI, ZJ>(x: X, y: Y, z: ZI) -> Self
1864 where
1865 X: IntoIterator<Item = f64>,
1866 Y: IntoIterator<Item = f64>,
1867 ZI: IntoIterator<Item = ZJ>,
1868 ZJ: IntoIterator<Item = f64>,
1869 {
1870 let x: Vec<f64> = x.into_iter().collect();
1871 let y: Vec<f64> = y.into_iter().collect();
1872 let z: Vec<Vec<f64>> =
1873 z.into_iter()
1874 .map(|row| row.into_iter().collect())
1875 .collect();
1876 Self { x, y, z, opts: Vec::new() }
1877 }
1878
1879 pub fn new_flat<X, Y, Z>(x: X, y: Y, z: Z) -> Self
1884 where
1885 X: IntoIterator<Item = f64>,
1886 Y: IntoIterator<Item = f64>,
1887 Z: IntoIterator<Item = f64>,
1888 {
1889 let x: Vec<f64> = x.into_iter().collect();
1890 if x.is_empty() { panic!("x-coordinate array cannot be empty"); }
1891 let y: Vec<f64> = y.into_iter().collect();
1892 let z: Vec<Vec<f64>> =
1893 Chunks::new(z.into_iter(), x.len())
1894 .collect();
1895 Self { x, y, z, opts: Vec::new() }
1896 }
1897}
1898
1899pub fn contour<X, Y, ZI, ZJ>(x: X, y: Y, z: ZI) -> Contour
1901where
1902 X: IntoIterator<Item = f64>,
1903 Y: IntoIterator<Item = f64>,
1904 ZI: IntoIterator<Item = ZJ>,
1905 ZJ: IntoIterator<Item = f64>,
1906{
1907 Contour::new(x, y, z)
1908}
1909
1910pub fn contour_flat<X, Y, Z>(x: X, y: Y, z: Z) -> Contour
1915where
1916 X: IntoIterator<Item = f64>,
1917 Y: IntoIterator<Item = f64>,
1918 Z: IntoIterator<Item = f64>,
1919{
1920 Contour::new_flat(x, y, z)
1921}
1922
1923impl Matplotlib for Contour {
1924 fn is_prelude(&self) -> bool { false }
1925
1926 fn data(&self) -> Option<Value> {
1927 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
1928 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
1929 let z: Vec<Value> =
1930 self.z.iter()
1931 .map(|row| {
1932 let row: Vec<Value> =
1933 row.iter().copied().map(Value::from).collect();
1934 Value::Array(row)
1935 })
1936 .collect();
1937 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
1938 }
1939
1940 fn py_cmd(&self) -> String {
1941 format!("im = ax.contour(data[0], data[1], data[2]{}{})",
1942 if self.opts.is_empty() { "" } else { ", " },
1943 self.opts.as_py(),
1944 )
1945 }
1946}
1947
1948impl MatplotlibOpts for Contour {
1949 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
1950 self.opts.push((key, val).into());
1951 self
1952 }
1953}
1954
1955#[derive(Clone, Debug, PartialEq)]
1970pub struct Contourf {
1971 pub x: Vec<f64>,
1973 pub y: Vec<f64>,
1975 pub z: Vec<Vec<f64>>,
1979 pub opts: Vec<Opt>,
1981}
1982
1983impl Contourf {
1984 pub fn new<X, Y, ZI, ZJ>(x: X, y: Y, z: ZI) -> Self
1986 where
1987 X: IntoIterator<Item = f64>,
1988 Y: IntoIterator<Item = f64>,
1989 ZI: IntoIterator<Item = ZJ>,
1990 ZJ: IntoIterator<Item = f64>,
1991 {
1992 let x: Vec<f64> = x.into_iter().collect();
1993 let y: Vec<f64> = y.into_iter().collect();
1994 let z: Vec<Vec<f64>> =
1995 z.into_iter()
1996 .map(|row| row.into_iter().collect())
1997 .collect();
1998 Self { x, y, z, opts: Vec::new() }
1999 }
2000
2001 pub fn new_flat<X, Y, Z>(x: X, y: Y, z: Z) -> Self
2006 where
2007 X: IntoIterator<Item = f64>,
2008 Y: IntoIterator<Item = f64>,
2009 Z: IntoIterator<Item = f64>,
2010 {
2011 let x: Vec<f64> = x.into_iter().collect();
2012 if x.is_empty() { panic!("x-coordinate array cannot be empty"); }
2013 let y: Vec<f64> = y.into_iter().collect();
2014 let z: Vec<Vec<f64>> =
2015 Chunks::new(z.into_iter(), x.len())
2016 .collect();
2017 Self { x, y, z, opts: Vec::new() }
2018 }
2019}
2020
2021pub fn contourf<X, Y, ZI, ZJ>(x: X, y: Y, z: ZI) -> Contourf
2023where
2024 X: IntoIterator<Item = f64>,
2025 Y: IntoIterator<Item = f64>,
2026 ZI: IntoIterator<Item = ZJ>,
2027 ZJ: IntoIterator<Item = f64>,
2028{
2029 Contourf::new(x, y, z)
2030}
2031
2032pub fn contourf_flat<X, Y, Z>(x: X, y: Y, z: Z) -> Contourf
2037where
2038 X: IntoIterator<Item = f64>,
2039 Y: IntoIterator<Item = f64>,
2040 Z: IntoIterator<Item = f64>,
2041{
2042 Contourf::new_flat(x, y, z)
2043}
2044
2045impl Matplotlib for Contourf {
2046 fn is_prelude(&self) -> bool { false }
2047
2048 fn data(&self) -> Option<Value> {
2049 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
2050 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
2051 let z: Vec<Value> =
2052 self.z.iter()
2053 .map(|row| {
2054 let row: Vec<Value> =
2055 row.iter().copied().map(Value::from).collect();
2056 Value::Array(row)
2057 })
2058 .collect();
2059 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
2060 }
2061
2062 fn py_cmd(&self) -> String {
2063 format!("im = ax.contourf(data[0], data[1], data[2]{}{})",
2064 if self.opts.is_empty() { "" } else { ", " },
2065 self.opts.as_py(),
2066 )
2067 }
2068}
2069
2070impl MatplotlibOpts for Contourf {
2071 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2072 self.opts.push((key, val).into());
2073 self
2074 }
2075}
2076
2077#[derive(Clone, Debug, PartialEq)]
2090pub struct Imshow {
2091 pub data: Vec<Vec<f64>>,
2093 pub opts: Vec<Opt>,
2095}
2096
2097impl Imshow {
2098 pub fn new<I, J>(data: I) -> Self
2100 where
2101 I: IntoIterator<Item = J>,
2102 J: IntoIterator<Item = f64>,
2103 {
2104 let data: Vec<Vec<f64>> =
2105 data.into_iter()
2106 .map(|row| row.into_iter().collect())
2107 .collect();
2108 Self { data, opts: Vec::new() }
2109 }
2110
2111 pub fn new_flat<I>(data: I, rowlen: usize) -> Self
2116 where I: IntoIterator<Item = f64>
2117 {
2118 if rowlen == 0 { panic!("row length cannot be zero"); }
2119 let data: Vec<Vec<f64>> =
2120 Chunks::new(data.into_iter(), rowlen)
2121 .collect();
2122 Self { data, opts: Vec::new() }
2123 }
2124}
2125
2126pub fn imshow<I, J>(data: I) -> Imshow
2128where
2129 I: IntoIterator<Item = J>,
2130 J: IntoIterator<Item = f64>,
2131{
2132 Imshow::new(data)
2133}
2134
2135pub fn imshow_flat<I>(data: I, rowlen: usize) -> Imshow
2140where I: IntoIterator<Item = f64>
2141{
2142 Imshow::new_flat(data, rowlen)
2143}
2144
2145impl Matplotlib for Imshow {
2146 fn is_prelude(&self) -> bool { false }
2147
2148 fn data(&self) -> Option<Value> {
2149 let data: Vec<Value> =
2150 self.data.iter()
2151 .map(|row| {
2152 let row: Vec<Value> =
2153 row.iter().copied().map(Value::from).collect();
2154 Value::Array(row)
2155 })
2156 .collect();
2157 Some(Value::Array(data))
2158 }
2159
2160 fn py_cmd(&self) -> String {
2161 format!("im = ax.imshow(data{}{})",
2162 if self.opts.is_empty() { "" } else { ", " },
2163 self.opts.as_py(),
2164 )
2165 }
2166}
2167
2168impl MatplotlibOpts for Imshow {
2169 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2170 self.opts.push((key, val).into());
2171 self
2172 }
2173}
2174
2175#[derive(Clone, Debug, PartialEq)]
2185pub struct FillBetween {
2186 pub x: Vec<f64>,
2188 pub y1: Vec<f64>,
2190 pub y2: Vec<f64>,
2192 pub opts: Vec<Opt>,
2194}
2195
2196impl FillBetween {
2197 pub fn new<X, Y1, Y2>(x: X, y1: Y1, y2: Y2) -> Self
2199 where
2200 X: IntoIterator<Item = f64>,
2201 Y1: IntoIterator<Item = f64>,
2202 Y2: IntoIterator<Item = f64>,
2203 {
2204 Self {
2205 x: x.into_iter().collect(),
2206 y1: y1.into_iter().collect(),
2207 y2: y2.into_iter().collect(),
2208 opts: Vec::new(),
2209 }
2210 }
2211
2212 pub fn new_data<I>(data: I) -> Self
2214 where I: IntoIterator<Item = (f64, f64, f64)>
2215 {
2216 let ((x, y1), y2) = data.into_iter().map(assoc).unzip();
2217 Self { x, y1, y2, opts: Vec::new() }
2218 }
2219}
2220
2221pub fn fill_between<X, Y1, Y2>(x: X, y1: Y1, y2: Y2) -> FillBetween
2223where
2224 X: IntoIterator<Item = f64>,
2225 Y1: IntoIterator<Item = f64>,
2226 Y2: IntoIterator<Item = f64>,
2227{
2228 FillBetween::new(x, y1, y2)
2229}
2230
2231pub fn fill_between_data<I>(data: I) -> FillBetween
2233where I: IntoIterator<Item = (f64, f64, f64)>
2234{
2235 FillBetween::new_data(data)
2236}
2237
2238impl Matplotlib for FillBetween {
2239 fn is_prelude(&self) -> bool { false }
2240
2241 fn data(&self) -> Option<Value> {
2242 let x: Vec<Value> =
2243 self.x.iter().copied().map(Value::from).collect();
2244 let y1: Vec<Value> =
2245 self.y1.iter().copied().map(Value::from).collect();
2246 let y2: Vec<Value> =
2247 self.y2.iter().copied().map(Value::from).collect();
2248 Some(Value::Array(vec![x.into(), y1.into(), y2.into()]))
2249 }
2250
2251 fn py_cmd(&self) -> String {
2252 format!("ax.fill_between(data[0], data[1], data[2]{}{})",
2253 if self.opts.is_empty() { "" } else { ", " },
2254 self.opts.as_py(),
2255 )
2256 }
2257}
2258
2259impl MatplotlibOpts for FillBetween {
2260 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2261 self.opts.push((key, val).into());
2262 self
2263 }
2264}
2265
2266impl From<Errorbar> for FillBetween {
2268 fn from(errorbar: Errorbar) -> Self {
2269 let Errorbar { x, mut y, mut e, opts } = errorbar;
2270 y.iter_mut()
2271 .zip(e.iter_mut())
2272 .for_each(|(yk, ek)| {
2273 let y = *yk;
2274 let e = *ek;
2275 *yk -= e;
2276 *ek += y;
2277 });
2278 Self { x, y1: y, y2: e, opts }
2279 }
2280}
2281
2282impl From<Errorbar2> for FillBetween {
2284 fn from(errorbar2: Errorbar2) -> Self {
2285 let Errorbar2 { x, mut y, mut e_neg, e_pos, opts } = errorbar2;
2286 y.iter_mut()
2287 .zip(e_neg.iter_mut().zip(e_pos.iter()))
2288 .for_each(|(yk, (emk, epk))| {
2289 let y = *yk;
2290 let em = *emk;
2291 let ep = *epk;
2292 *yk -= em;
2293 *emk = y + ep;
2294 });
2295 Self { x, y1: y, y2: e_neg, opts }
2296 }
2297}
2298
2299#[derive(Clone, Debug, PartialEq)]
2309pub struct FillBetweenX {
2310 pub y: Vec<f64>,
2312 pub x1: Vec<f64>,
2314 pub x2: Vec<f64>,
2316 pub opts: Vec<Opt>,
2318}
2319
2320impl FillBetweenX {
2321 pub fn new<Y, X1, X2>(y: Y, x1: X1, x2: X2) -> Self
2323 where
2324 Y: IntoIterator<Item = f64>,
2325 X1: IntoIterator<Item = f64>,
2326 X2: IntoIterator<Item = f64>,
2327 {
2328 Self {
2329 y: y.into_iter().collect(),
2330 x1: x1.into_iter().collect(),
2331 x2: x2.into_iter().collect(),
2332 opts: Vec::new(),
2333 }
2334 }
2335
2336 pub fn new_data<I>(data: I) -> Self
2338 where I: IntoIterator<Item = (f64, f64, f64)>
2339 {
2340 let ((y, x1), x2) = data.into_iter().map(assoc).unzip();
2341 Self { y, x1, x2, opts: Vec::new() }
2342 }
2343}
2344
2345pub fn fill_betweenx<Y, X1, X2>(y: Y, x1: X1, x2: X2) -> FillBetweenX
2347where
2348 Y: IntoIterator<Item = f64>,
2349 X1: IntoIterator<Item = f64>,
2350 X2: IntoIterator<Item = f64>,
2351{
2352 FillBetweenX::new(y, x1, x2)
2353}
2354
2355pub fn fill_betweenx_data<I>(data: I) -> FillBetweenX
2357where I: IntoIterator<Item = (f64, f64, f64)>
2358{
2359 FillBetweenX::new_data(data)
2360}
2361
2362impl Matplotlib for FillBetweenX {
2363 fn is_prelude(&self) -> bool { false }
2364
2365 fn data(&self) -> Option<Value> {
2366 let y: Vec<Value> =
2367 self.y.iter().copied().map(Value::from).collect();
2368 let x1: Vec<Value> =
2369 self.x1.iter().copied().map(Value::from).collect();
2370 let x2: Vec<Value> =
2371 self.x2.iter().copied().map(Value::from).collect();
2372 Some(Value::Array(vec![y.into(), x1.into(), x2.into()]))
2373 }
2374
2375 fn py_cmd(&self) -> String {
2376 format!("ax.fill_betweenx(data[0], data[1], data[2]{}{})",
2377 if self.opts.is_empty() { "" } else { ", " },
2378 self.opts.as_py(),
2379 )
2380 }
2381}
2382
2383impl MatplotlibOpts for FillBetweenX {
2384 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2385 self.opts.push((key, val).into());
2386 self
2387 }
2388}
2389
2390#[derive(Clone, Debug, PartialEq)]
2400pub struct AxHLine {
2401 pub y: f64,
2403 pub opts: Vec<Opt>,
2405}
2406
2407impl AxHLine {
2408 pub fn new(y: f64) -> Self {
2410 Self { y, opts: Vec::new() }
2411 }
2412}
2413
2414pub fn axhline(y: f64) -> AxHLine { AxHLine::new(y) }
2416
2417impl Matplotlib for AxHLine {
2418 fn is_prelude(&self) -> bool { false }
2419
2420 fn data(&self) -> Option<Value> { None }
2421
2422 fn py_cmd(&self) -> String {
2423 format!("ax.axhline({}{}{})",
2424 self.y.as_py(),
2425 if self.opts.is_empty() { "" } else { ", " },
2426 self.opts.as_py(),
2427 )
2428 }
2429}
2430
2431impl MatplotlibOpts for AxHLine {
2432 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2433 self.opts.push((key, val).into());
2434 self
2435 }
2436}
2437
2438#[derive(Clone, Debug, PartialEq)]
2448pub struct AxVLine {
2449 pub x: f64,
2451 pub opts: Vec<Opt>,
2453}
2454
2455impl AxVLine {
2456 pub fn new(x: f64) -> Self {
2458 Self { x, opts: Vec::new() }
2459 }
2460}
2461
2462pub fn axvline(x: f64) -> AxVLine { AxVLine::new(x) }
2464
2465impl Matplotlib for AxVLine {
2466 fn is_prelude(&self) -> bool { false }
2467
2468 fn data(&self) -> Option<Value> { None }
2469
2470 fn py_cmd(&self) -> String {
2471 format!("ax.axvline({}{}{})",
2472 self.x.as_py(),
2473 if self.opts.is_empty() { "" } else { ", " },
2474 self.opts.as_py(),
2475 )
2476 }
2477}
2478
2479impl MatplotlibOpts for AxVLine {
2480 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2481 self.opts.push((key, val).into());
2482 self
2483 }
2484}
2485
2486#[derive(Clone, Debug, PartialEq)]
2492pub struct AxLine {
2493 pub xy1: (f64, f64),
2495 pub xy2: (f64, f64),
2497 pub opts: Vec<Opt>,
2499}
2500
2501impl AxLine {
2502 pub fn new(xy1: (f64, f64), xy2: (f64, f64)) -> Self {
2504 Self { xy1, xy2, opts: Vec::new() }
2505 }
2506}
2507
2508pub fn axline(xy1: (f64, f64), xy2: (f64, f64)) -> AxLine {
2510 AxLine::new(xy1, xy2)
2511}
2512
2513impl Matplotlib for AxLine {
2514 fn is_prelude(&self) -> bool { false }
2515
2516 fn data(&self) -> Option<Value> { None }
2517
2518 fn py_cmd(&self) -> String {
2519 format!("ax.axline({}, {}{}{})",
2520 self.xy1.as_py(),
2521 self.xy2.as_py(),
2522 if self.opts.is_empty() { "" } else { ", " },
2523 self.opts.as_py(),
2524 )
2525 }
2526}
2527
2528impl MatplotlibOpts for AxLine {
2529 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2530 self.opts.push((key, val).into());
2531 self
2532 }
2533}
2534
2535#[derive(Clone, Debug, PartialEq)]
2541pub struct AxLineM {
2542 pub xy: (f64, f64),
2544 pub m: f64,
2546 pub opts: Vec<Opt>,
2548}
2549
2550impl AxLineM {
2551 pub fn new(xy: (f64, f64), m: f64) -> Self {
2553 Self { xy, m, opts: Vec::new() }
2554 }
2555}
2556
2557pub fn axlinem(xy: (f64, f64), m: f64) -> AxLineM { AxLineM::new(xy, m) }
2559
2560impl Matplotlib for AxLineM {
2561 fn is_prelude(&self) -> bool { false }
2562
2563 fn data(&self) -> Option<Value> { None }
2564
2565 fn py_cmd(&self) -> String {
2566 format!("ax.axline({}, xy2=None, slope={}{}{})",
2567 self.xy.as_py(),
2568 self.m.as_py(),
2569 if self.opts.is_empty() { "" } else { ", " },
2570 self.opts.as_py(),
2571 )
2572 }
2573}
2574
2575impl MatplotlibOpts for AxLineM {
2576 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2577 self.opts.push((key, val).into());
2578 self
2579 }
2580}
2581
2582#[derive(Clone, Debug, PartialEq)]
2592pub struct Pie {
2593 pub data: Vec<f64>,
2595 pub opts: Vec<Opt>,
2597}
2598
2599impl Pie {
2600 pub fn new<I>(data: I) -> Self
2602 where I: IntoIterator<Item = f64>
2603 {
2604 Self { data: data.into_iter().collect(), opts: Vec::new() }
2605 }
2606}
2607
2608pub fn pie<I>(data: I) -> Pie
2610where I: IntoIterator<Item = f64>
2611{
2612 Pie::new(data)
2613}
2614
2615impl Matplotlib for Pie {
2616 fn is_prelude(&self) -> bool { false }
2617
2618 fn data(&self) -> Option<Value> {
2619 Some(Value::Array(
2620 self.data.iter().copied().map(Value::from).collect()))
2621 }
2622
2623 fn py_cmd(&self) -> String {
2624 format!("ax.pie(data{}{})",
2625 if self.opts.is_empty() { "" } else { ", " },
2626 self.opts.as_py(),
2627 )
2628 }
2629}
2630
2631impl MatplotlibOpts for Pie {
2632 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2633 self.opts.push((key, val).into());
2634 self
2635 }
2636}
2637
2638#[derive(Clone, Debug, PartialEq)]
2650pub struct Text {
2651 pub x: f64,
2653 pub y: f64,
2655 pub s: String,
2657 pub opts: Vec<Opt>,
2659}
2660
2661impl Text {
2662 pub fn new(x: f64, y: f64, s: &str) -> Self {
2664 Self { x, y, s: s.into(), opts: Vec::new() }
2665 }
2666}
2667
2668pub fn text(x: f64, y: f64, s: &str) -> Text { Text::new(x, y, s) }
2670
2671impl Matplotlib for Text {
2672 fn is_prelude(&self) -> bool { false }
2673
2674 fn data(&self) -> Option<Value> {
2675 Some(Value::Array(
2676 vec![self.x.into(), self.y.into(), (&*self.s).into()]))
2677 }
2678
2679 fn py_cmd(&self) -> String {
2680 format!("ax.text(data[0], data[1], data[2]{}{})",
2681 if self.opts.is_empty() { "" } else { ", " },
2682 self.opts.as_py(),
2683 )
2684 }
2685}
2686
2687impl MatplotlibOpts for Text {
2688 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2689 self.opts.push((key, val).into());
2690 self
2691 }
2692}
2693
2694#[derive(Clone, Debug, PartialEq)]
2704pub struct AxText {
2705 pub x: f64,
2707 pub y: f64,
2709 pub s: String,
2711 pub opts: Vec<Opt>,
2713}
2714
2715impl AxText {
2716 pub fn new(x: f64, y: f64, s: &str) -> Self {
2718 Self { x, y, s: s.into(), opts: Vec::new() }
2719 }
2720}
2721
2722pub fn axtext(x: f64, y: f64, s: &str) -> AxText { AxText::new(x, y, s) }
2724
2725impl Matplotlib for AxText {
2726 fn is_prelude(&self) -> bool { false }
2727
2728 fn data(&self) -> Option<Value> {
2729 Some(Value::Array(
2730 vec![self.x.into(), self.y.into(), (&*self.s).into()]))
2731 }
2732
2733 fn py_cmd(&self) -> String {
2734 format!(
2735 "ax.text(data[0], data[1], data[2], transform=ax.transAxes{}{})",
2736 if self.opts.is_empty() { "" } else { ", " },
2737 self.opts.as_py(),
2738 )
2739 }
2740}
2741
2742impl MatplotlibOpts for AxText {
2743 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2744 self.opts.push((key, val).into());
2745 self
2746 }
2747}
2748
2749#[derive(Clone, Debug, PartialEq)]
2762pub struct FigText {
2763 pub x: f64,
2765 pub y: f64,
2767 pub s: String,
2769 pub opts: Vec<Opt>,
2771}
2772
2773impl FigText {
2774 pub fn new(x: f64, y: f64, s: &str) -> Self {
2776 Self { x, y, s: s.into(), opts: Vec::new() }
2777 }
2778}
2779
2780pub fn figtext(x: f64, y: f64, s: &str) -> FigText { FigText::new(x, y, s) }
2782
2783impl Matplotlib for FigText {
2784 fn is_prelude(&self) -> bool { false }
2785
2786 fn data(&self) -> Option<Value> {
2787 Some(Value::Array(
2788 vec![self.x.into(), self.y.into(), (&*self.s).into()]))
2789 }
2790
2791 fn py_cmd(&self) -> String {
2792 format!(
2793 "fig.text(data[0], data[1], data[2]{}{})",
2794 if self.opts.is_empty() { "" } else { ", " },
2795 self.opts.as_py(),
2796 )
2797 }
2798}
2799
2800impl MatplotlibOpts for FigText {
2801 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2802 self.opts.push((key, val).into());
2803 self
2804 }
2805}
2806
2807#[derive(Clone, Debug, PartialEq)]
2822pub struct Colorbar {
2823 pub opts: Vec<Opt>,
2825}
2826
2827impl Default for Colorbar {
2828 fn default() -> Self { Self::new() }
2829}
2830
2831impl Colorbar {
2832 pub fn new() -> Self { Self { opts: Vec::new() } }
2834}
2835
2836pub fn colorbar() -> Colorbar { Colorbar::new() }
2838
2839impl Matplotlib for Colorbar {
2840 fn is_prelude(&self) -> bool { false }
2841
2842 fn data(&self) -> Option<Value> { None }
2843
2844 fn py_cmd(&self) -> String {
2845 format!("cbar = fig.colorbar(im, ax=ax{}{})",
2846 if self.opts.is_empty() { "" } else { ", " },
2847 self.opts.as_py(),
2848 )
2849 }
2850}
2851
2852impl MatplotlibOpts for Colorbar {
2853 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
2854 self.opts.push((key, val).into());
2855 self
2856 }
2857}
2858
2859#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2869pub struct Scale {
2870 pub axis: Axis,
2872 pub scale: AxisScale,
2874}
2875
2876impl Scale {
2877 pub fn new(axis: Axis, scale: AxisScale) -> Self { Self { axis, scale } }
2879}
2880
2881pub fn scale(axis: Axis, scale: AxisScale) -> Scale { Scale::new(axis, scale) }
2883
2884pub fn xscale(scale: AxisScale) -> Scale { Scale::new(Axis::X, scale) }
2886
2887pub fn yscale(scale: AxisScale) -> Scale { Scale::new(Axis::Y, scale) }
2889
2890pub fn zscale(scale: AxisScale) -> Scale { Scale::new(Axis::Z, scale) }
2892
2893impl Matplotlib for Scale {
2894 fn is_prelude(&self) -> bool { false }
2895
2896 fn data(&self) -> Option<Value> { None }
2897
2898 fn py_cmd(&self) -> String {
2899 let ax = format!("{:?}", self.axis).to_lowercase();
2900 let sc = format!("{:?}", self.scale).to_lowercase();
2901 format!("ax.set_{}scale(\"{}\")", ax, sc)
2902 }
2903}
2904
2905#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2907pub enum Axis {
2908 X,
2910 Y,
2912 Z,
2914}
2915
2916#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2918pub enum AxisScale {
2919 Linear,
2921 Log,
2923 SymLog,
2927 Logit,
2935}
2936
2937#[derive(Copy, Clone, Debug, PartialEq)]
2947pub struct Lim {
2948 pub axis: Axis,
2950 pub min: Option<f64>,
2954 pub max: Option<f64>,
2958}
2959
2960impl Lim {
2961 pub fn new(axis: Axis, min: Option<f64>, max: Option<f64>) -> Self {
2963 Self { axis, min, max }
2964 }
2965}
2966
2967pub fn lim(axis: Axis, min: Option<f64>, max: Option<f64>) -> Lim {
2969 Lim::new(axis, min, max)
2970}
2971
2972pub fn xlim(min: Option<f64>, max: Option<f64>) -> Lim {
2974 Lim::new(Axis::X, min, max)
2975}
2976
2977pub fn ylim(min: Option<f64>, max: Option<f64>) -> Lim {
2979 Lim::new(Axis::Y, min, max)
2980}
2981
2982pub fn zlim(min: Option<f64>, max: Option<f64>) -> Lim {
2984 Lim::new(Axis::Z, min, max)
2985}
2986
2987impl Matplotlib for Lim {
2988 fn is_prelude(&self) -> bool { false }
2989
2990 fn data(&self) -> Option<Value> { None }
2991
2992 fn py_cmd(&self) -> String {
2993 let ax = format!("{:?}", self.axis).to_lowercase();
2994 let min =
2995 self.min.as_ref()
2996 .map(|x| x.as_py())
2997 .unwrap_or("None".into());
2998 let max =
2999 self.max.as_ref()
3000 .map(|x| x.as_py())
3001 .unwrap_or("None".into());
3002 format!("ax.set_{}lim({}, {})", ax, min, max)
3003 }
3004}
3005
3006#[derive(Copy, Clone, Debug, PartialEq)]
3018pub struct CLim {
3019 pub min: Option<f64>,
3023 pub max: Option<f64>,
3027}
3028
3029impl CLim {
3030 pub fn new(min: Option<f64>, max: Option<f64>) -> Self {
3032 Self { min, max }
3033 }
3034}
3035
3036pub fn clim(min: Option<f64>, max: Option<f64>) -> CLim { CLim::new(min, max) }
3038
3039impl Matplotlib for CLim {
3040 fn is_prelude(&self) -> bool { false }
3041
3042 fn data(&self) -> Option<Value> { None }
3043
3044 fn py_cmd(&self) -> String {
3045 let min =
3046 self.min.as_ref()
3047 .map(|x| x.as_py())
3048 .unwrap_or("None".into());
3049 let max =
3050 self.max.as_ref()
3051 .map(|x| x.as_py())
3052 .unwrap_or("None".into());
3053 format!("im.set_clim({}, {})", min, max)
3054 }
3055}
3056
3057#[derive(Clone, Debug, PartialEq)]
3067pub struct Title {
3068 pub s: String,
3070 pub opts: Vec<Opt>,
3072}
3073
3074impl Title {
3075 pub fn new(s: &str) -> Self {
3077 Self { s: s.into(), opts: Vec::new() }
3078 }
3079}
3080
3081pub fn title(s: &str) -> Title { Title::new(s) }
3083
3084impl Matplotlib for Title {
3085 fn is_prelude(&self) -> bool { false }
3086
3087 fn data(&self) -> Option<Value> { None }
3088
3089 fn py_cmd(&self) -> String {
3090 format!("ax.set_title({}{}{})",
3091 self.s.as_py(),
3092 if self.opts.is_empty() { "" } else { ", " },
3093 self.opts.as_py(),
3094 )
3095 }
3096}
3097
3098impl MatplotlibOpts for Title {
3099 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3100 self.opts.push((key, val).into());
3101 self
3102 }
3103}
3104
3105#[derive(Clone, Debug, PartialEq)]
3115pub struct Label {
3116 pub axis: Axis,
3118 pub s: String,
3120 pub opts: Vec<Opt>,
3122}
3123
3124impl Label {
3125 pub fn new(axis: Axis, s: &str) -> Self {
3127 Self { axis, s: s.into(), opts: Vec::new() }
3128 }
3129}
3130
3131pub fn label(axis: Axis, s: &str) -> Label { Label::new(axis, s) }
3133
3134pub fn xlabel(s: &str) -> Label { Label::new(Axis::X, s) }
3136
3137pub fn ylabel(s: &str) -> Label { Label::new(Axis::Y, s) }
3139
3140pub fn zlabel(s: &str) -> Label { Label::new(Axis::Z, s) }
3142
3143impl Matplotlib for Label {
3144 fn is_prelude(&self) -> bool { false }
3145
3146 fn data(&self) -> Option<Value> { None }
3147
3148 fn py_cmd(&self) -> String {
3149 let ax = format!("{:?}", self.axis).to_lowercase();
3150 format!("ax.set_{}label({}{}{})",
3151 ax,
3152 self.s.as_py(),
3153 if self.opts.is_empty() { "" } else { ", " },
3154 self.opts.as_py(),
3155 )
3156 }
3157}
3158
3159impl MatplotlibOpts for Label {
3160 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3161 self.opts.push((key, val).into());
3162 self
3163 }
3164}
3165
3166#[derive(Clone, Debug, PartialEq)]
3179pub struct CLabel {
3180 pub s: String,
3182 pub opts: Vec<Opt>,
3184}
3185
3186impl CLabel {
3187 pub fn new(s: &str) -> Self {
3189 Self { s: s.into(), opts: Vec::new() }
3190 }
3191}
3192
3193pub fn clabel(s: &str) -> CLabel { CLabel::new(s) }
3195
3196impl Matplotlib for CLabel {
3197 fn is_prelude(&self) -> bool { false }
3198
3199 fn data(&self) -> Option<Value> { None }
3200
3201 fn py_cmd(&self) -> String {
3202 format!("cbar.set_label({}{}{})",
3203 self.s.as_py(),
3204 if self.opts.is_empty() { "" } else { ", " },
3205 self.opts.as_py(),
3206 )
3207 }
3208}
3209
3210impl MatplotlibOpts for CLabel {
3211 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3212 self.opts.push((key, val).into());
3213 self
3214 }
3215}
3216
3217#[derive(Clone, Debug, PartialEq)]
3227pub struct Ticks {
3228 pub axis: Axis,
3230 pub v: Vec<f64>,
3232 pub opts: Vec<Opt>,
3234}
3235
3236impl Ticks {
3237 pub fn new<I>(axis: Axis, v: I) -> Self
3239 where I: IntoIterator<Item = f64>
3240 {
3241 Self { axis, v: v.into_iter().collect(), opts: Vec::new() }
3242 }
3243}
3244
3245pub fn ticks<I>(axis: Axis, v: I) -> Ticks
3247where I: IntoIterator<Item = f64>
3248{
3249 Ticks::new(axis, v)
3250}
3251
3252pub fn xticks<I>(v: I) -> Ticks
3254where I: IntoIterator<Item = f64>
3255{
3256 Ticks::new(Axis::X, v)
3257}
3258
3259pub fn yticks<I>(v: I) -> Ticks
3261where I: IntoIterator<Item = f64>
3262{
3263 Ticks::new(Axis::Y, v)
3264}
3265
3266pub fn zticks<I>(v: I) -> Ticks
3268where I: IntoIterator<Item = f64>
3269{
3270 Ticks::new(Axis::Z, v)
3271}
3272
3273impl Matplotlib for Ticks {
3274 fn is_prelude(&self) -> bool { false }
3275
3276 fn data(&self) -> Option<Value> {
3277 let v: Vec<Value> = self.v.iter().copied().map(Value::from).collect();
3278 Some(Value::Array(v))
3279 }
3280
3281 fn py_cmd(&self) -> String {
3282 format!("ax.set_{}ticks(data{}{})",
3283 format!("{:?}", self.axis).to_lowercase(),
3284 if self.opts.is_empty() { "" } else { ", " },
3285 self.opts.as_py(),
3286 )
3287 }
3288}
3289
3290impl MatplotlibOpts for Ticks {
3291 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3292 self.opts.push((key, val).into());
3293 self
3294 }
3295}
3296
3297#[derive(Clone, Debug, PartialEq)]
3310pub struct CTicks {
3311 pub v: Vec<f64>,
3313 pub opts: Vec<Opt>,
3315}
3316
3317impl CTicks {
3318 pub fn new<I>(v: I) -> Self
3320 where I: IntoIterator<Item = f64>
3321 {
3322 Self { v: v.into_iter().collect(), opts: Vec::new() }
3323 }
3324}
3325
3326pub fn cticks<I>(v: I) -> CTicks
3328where I: IntoIterator<Item = f64>
3329{
3330 CTicks::new(v)
3331}
3332
3333impl Matplotlib for CTicks {
3334 fn is_prelude(&self) -> bool { false }
3335
3336 fn data(&self) -> Option<Value> {
3337 let v: Vec<Value> =
3338 self.v.iter().copied().map(Value::from).collect();
3339 Some(Value::Array(v))
3340 }
3341
3342 fn py_cmd(&self) -> String {
3343 format!("cbar.set_ticks(data{}{})",
3344 if self.opts.is_empty() { "" } else { ", " },
3345 self.opts.as_py(),
3346 )
3347 }
3348}
3349
3350impl MatplotlibOpts for CTicks {
3351 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3352 self.opts.push((key, val).into());
3353 self
3354 }
3355}
3356
3357#[derive(Clone, Debug, PartialEq)]
3367pub struct TickLabels {
3368 pub axis: Axis,
3370 pub v: Vec<f64>,
3372 pub s: Vec<String>,
3374 pub opts: Vec<Opt>,
3376}
3377
3378impl TickLabels {
3379 pub fn new<I, J, S>(axis: Axis, v: I, s: J) -> Self
3381 where
3382 I: IntoIterator<Item = f64>,
3383 J: IntoIterator<Item = S>,
3384 S: Into<String>,
3385 {
3386 Self {
3387 axis,
3388 v: v.into_iter().collect(),
3389 s: s.into_iter().map(|sk| sk.into()).collect(),
3390 opts: Vec::new(),
3391 }
3392 }
3393
3394 pub fn new_data<I, S>(axis: Axis, ticklabels: I) -> Self
3396 where
3397 I: IntoIterator<Item = (f64, S)>,
3398 S: Into<String>,
3399 {
3400 let (v, s): (Vec<f64>, Vec<String>) =
3401 ticklabels.into_iter()
3402 .map(|(vk, sk)| (vk, sk.into()))
3403 .unzip();
3404 Self { axis, v, s, opts: Vec::new() }
3405 }
3406}
3407
3408pub fn ticklabels<I, J, S>(axis: Axis, v: I, s: J) -> TickLabels
3410where
3411 I: IntoIterator<Item = f64>,
3412 J: IntoIterator<Item = S>,
3413 S: Into<String>,
3414{
3415 TickLabels::new(axis, v, s)
3416}
3417
3418pub fn ticklabels_data<I, S>(axis: Axis, ticklabels: I) -> TickLabels
3420where
3421 I: IntoIterator<Item = (f64, S)>,
3422 S: Into<String>,
3423{
3424 TickLabels::new_data(axis, ticklabels)
3425}
3426
3427pub fn xticklabels<I, J, S>(v: I, s: J) -> TickLabels
3429where
3430 I: IntoIterator<Item = f64>,
3431 J: IntoIterator<Item = S>,
3432 S: Into<String>,
3433{
3434 TickLabels::new(Axis::X, v, s)
3435}
3436
3437pub fn xticklabels_data<I, S>(ticklabels: I) -> TickLabels
3440where
3441 I: IntoIterator<Item = (f64, S)>,
3442 S: Into<String>,
3443{
3444 TickLabels::new_data(Axis::X, ticklabels)
3445}
3446
3447pub fn yticklabels<I, J, S>(v: I, s: J) -> TickLabels
3449where
3450 I: IntoIterator<Item = f64>,
3451 J: IntoIterator<Item = S>,
3452 S: Into<String>,
3453{
3454 TickLabels::new(Axis::Y, v, s)
3455}
3456
3457pub fn yticklabels_data<I, S>(ticklabels: I) -> TickLabels
3460where
3461 I: IntoIterator<Item = (f64, S)>,
3462 S: Into<String>,
3463{
3464 TickLabels::new_data(Axis::Y, ticklabels)
3465}
3466
3467pub fn zticklabels<I, J, S>(v: I, s: J) -> TickLabels
3469where
3470 I: IntoIterator<Item = f64>,
3471 J: IntoIterator<Item = S>,
3472 S: Into<String>,
3473{
3474 TickLabels::new(Axis::Z, v, s)
3475}
3476
3477pub fn zticklabels_data<I, S>(ticklabels: I) -> TickLabels
3480where
3481 I: IntoIterator<Item = (f64, S)>,
3482 S: Into<String>,
3483{
3484 TickLabels::new_data(Axis::Z, ticklabels)
3485}
3486
3487impl Matplotlib for TickLabels {
3488 fn is_prelude(&self) -> bool { false }
3489
3490 fn data(&self) -> Option<Value> {
3491 let v: Vec<Value> = self.v.iter().copied().map(Value::from).collect();
3492 let s: Vec<Value> = self.s.iter().cloned().map(Value::from).collect();
3493 Some(Value::Array(vec![v.into(), s.into()]))
3494 }
3495
3496 fn py_cmd(&self) -> String {
3497 format!("ax.set_{}ticks(data[0], labels=data[1]{}{})",
3498 format!("{:?}", self.axis).to_lowercase(),
3499 if self.opts.is_empty() { "" } else { ", " },
3500 self.opts.as_py(),
3501 )
3502 }
3503}
3504
3505impl MatplotlibOpts for TickLabels {
3506 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3507 self.opts.push((key, val).into());
3508 self
3509 }
3510}
3511
3512#[derive(Clone, Debug, PartialEq)]
3525pub struct CTickLabels {
3526 pub v: Vec<f64>,
3528 pub s: Vec<String>,
3530 pub opts: Vec<Opt>,
3532}
3533
3534impl CTickLabels {
3535 pub fn new<I, J, S>(v: I, s: J) -> Self
3537 where
3538 I: IntoIterator<Item = f64>,
3539 J: IntoIterator<Item = S>,
3540 S: Into<String>,
3541 {
3542 Self {
3543 v: v.into_iter().collect(),
3544 s: s.into_iter().map(|sk| sk.into()).collect(),
3545 opts: Vec::new(),
3546 }
3547 }
3548
3549 pub fn new_data<I, S>(ticklabels: I) -> Self
3551 where
3552 I: IntoIterator<Item = (f64, S)>,
3553 S: Into<String>,
3554 {
3555 let (v, s): (Vec<f64>, Vec<String>) =
3556 ticklabels.into_iter()
3557 .map(|(vk, sk)| (vk, sk.into()))
3558 .unzip();
3559 Self { v, s, opts: Vec::new() }
3560 }
3561}
3562
3563pub fn cticklabels<I, J, S>(v: I, s: J) -> CTickLabels
3565where
3566 I: IntoIterator<Item = f64>,
3567 J: IntoIterator<Item = S>,
3568 S: Into<String>,
3569{
3570 CTickLabels::new(v, s)
3571}
3572
3573pub fn cticklabels_data<I, S>(ticklabels: I) -> CTickLabels
3575where
3576 I: IntoIterator<Item = (f64, S)>,
3577 S: Into<String>,
3578{
3579 CTickLabels::new_data(ticklabels)
3580}
3581
3582impl Matplotlib for CTickLabels {
3583 fn is_prelude(&self) -> bool { false }
3584
3585 fn data(&self) -> Option<Value> {
3586 let v: Vec<Value> =
3587 self.v.iter().copied().map(Value::from).collect();
3588 let s: Vec<Value> =
3589 self.s.iter().cloned().map(Value::from).collect();
3590 Some(Value::Array(vec![v.into(), s.into()]))
3591 }
3592
3593 fn py_cmd(&self) -> String {
3594 format!("cbar.set_ticks(data[0], labels=data[1]{}{})",
3595 if self.opts.is_empty() { "" } else { ", " },
3596 self.opts.as_py(),
3597 )
3598 }
3599}
3600
3601impl MatplotlibOpts for CTickLabels {
3602 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3603 self.opts.push((key, val).into());
3604 self
3605 }
3606}
3607
3608#[derive(Clone, Debug, PartialEq)]
3618pub struct TickParams {
3619 pub axis: Axis2,
3621 pub opts: Vec<Opt>,
3623}
3624
3625impl TickParams {
3626 pub fn new(axis: Axis2) -> Self {
3628 Self { axis, opts: Vec::new() }
3629 }
3630}
3631
3632pub fn tick_params(axis: Axis2) -> TickParams { TickParams::new(axis) }
3634
3635pub fn xtick_params() -> TickParams { TickParams::new(Axis2::X) }
3637
3638pub fn ytick_params() -> TickParams { TickParams::new(Axis2::Y) }
3640
3641impl Matplotlib for TickParams {
3642 fn is_prelude(&self) -> bool { false }
3643
3644 fn data(&self) -> Option<Value> { None }
3645
3646 fn py_cmd(&self) -> String {
3647 format!("ax.tick_params(\"{}\"{}{})",
3648 format!("{:?}", self.axis).to_lowercase(),
3649 if self.opts.is_empty() { "" } else { ", " },
3650 self.opts.as_py(),
3651 )
3652 }
3653}
3654
3655impl MatplotlibOpts for TickParams {
3656 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3657 self.opts.push((key, val).into());
3658 self
3659 }
3660}
3661
3662#[derive(Copy, Clone, Debug, PartialEq, Eq)]
3664pub enum Axis2 {
3665 X,
3667 Y,
3669 Both,
3671}
3672
3673#[derive(Clone, Debug, PartialEq)]
3683pub struct InvertAx {
3684 pub axis: Axis,
3686}
3687
3688impl InvertAx {
3689 pub fn new(axis: Axis) -> Self {
3691 Self { axis }
3692 }
3693}
3694
3695pub fn invert_ax(axis: Axis) -> InvertAx { InvertAx::new(axis) }
3697
3698pub fn invert_x() -> InvertAx { InvertAx::new(Axis::X) }
3700
3701pub fn invert_y() -> InvertAx { InvertAx::new(Axis::Y) }
3703
3704pub fn invert_z() -> InvertAx { InvertAx::new(Axis::Z) }
3706
3707impl Matplotlib for InvertAx {
3708 fn is_prelude(&self) -> bool { false }
3709
3710 fn data(&self) -> Option<Value> { None }
3711
3712 fn py_cmd(&self) -> String {
3713 let ax = format!("{:?}", self.axis).to_lowercase();
3714 format!("ax.invert_{}axis()", ax)
3715 }
3716}
3717
3718#[derive(Clone, Debug, PartialEq)]
3728pub struct Aspect {
3729 pub asp: f64,
3731 pub opts: Vec<Opt>,
3733}
3734
3735impl Aspect {
3736 pub fn new(asp: f64) -> Self {
3738 Self { asp, opts: Vec::new() }
3739 }
3740}
3741
3742pub fn aspect(asp: f64) -> Aspect { Aspect::new(asp) }
3744
3745impl Matplotlib for Aspect {
3746 fn is_prelude(&self) -> bool { false }
3747
3748 fn data(&self) -> Option<Value> { None }
3749
3750 fn py_cmd(&self) -> String {
3751 format!("ax.set_aspect({}{}{})",
3752 self.asp.as_py(),
3753 if self.opts.is_empty() { "" } else { ", " },
3754 self.opts.as_py(),
3755 )
3756 }
3757}
3758
3759impl MatplotlibOpts for Aspect {
3760 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3761 self.opts.push((key, val).into());
3762 self
3763 }
3764}
3765
3766#[derive(Clone, Debug, PartialEq)]
3776pub struct SupTitle {
3777 pub s: String,
3779 pub opts: Vec<Opt>,
3781}
3782
3783impl SupTitle {
3784 pub fn new(s: &str) -> Self {
3786 Self { s: s.into(), opts: Vec::new() }
3787 }
3788}
3789
3790pub fn suptitle(s: &str) -> SupTitle { SupTitle::new(s) }
3792
3793impl Matplotlib for SupTitle {
3794 fn is_prelude(&self) -> bool { false }
3795
3796 fn data(&self) -> Option<Value> { None }
3797
3798 fn py_cmd(&self) -> String {
3799 format!("fig.suptitle({}{}{})",
3800 self.s.as_py(),
3801 if self.opts.is_empty() { "" } else { ", " },
3802 self.opts.as_py(),
3803 )
3804 }
3805}
3806
3807impl MatplotlibOpts for SupTitle {
3808 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3809 self.opts.push((key, val).into());
3810 self
3811 }
3812}
3813
3814#[derive(Clone, Debug, PartialEq)]
3824pub struct SupXLabel {
3825 pub s: String,
3827 pub opts: Vec<Opt>,
3829}
3830
3831impl SupXLabel {
3832 pub fn new(s: &str) -> Self {
3834 Self { s: s.into(), opts: Vec::new() }
3835 }
3836}
3837
3838pub fn supxlabel(s: &str) -> SupXLabel { SupXLabel::new(s) }
3840
3841impl Matplotlib for SupXLabel {
3842 fn is_prelude(&self) -> bool { false }
3843
3844 fn data(&self) -> Option<Value> { None }
3845
3846 fn py_cmd(&self) -> String {
3847 format!("fig.supxlabel({}{}{})",
3848 self.s.as_py(),
3849 if self.opts.is_empty() { "" } else { ", " },
3850 self.opts.as_py(),
3851 )
3852 }
3853}
3854
3855impl MatplotlibOpts for SupXLabel {
3856 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3857 self.opts.push((key, val).into());
3858 self
3859 }
3860}
3861
3862#[derive(Clone, Debug, PartialEq)]
3872pub struct SupYLabel {
3873 pub s: String,
3875 pub opts: Vec<Opt>,
3877}
3878
3879impl SupYLabel {
3880 pub fn new(s: &str) -> Self {
3882 Self { s: s.into(), opts: Vec::new() }
3883 }
3884}
3885
3886pub fn supylabel(s: &str) -> SupYLabel { SupYLabel::new(s) }
3888
3889impl Matplotlib for SupYLabel {
3890 fn is_prelude(&self) -> bool { false }
3891
3892 fn data(&self) -> Option<Value> { None }
3893
3894 fn py_cmd(&self) -> String {
3895 format!("fig.supylabel({}{}{})",
3896 self.s.as_py(),
3897 if self.opts.is_empty() { "" } else { ", " },
3898 self.opts.as_py(),
3899 )
3900 }
3901}
3902
3903impl MatplotlibOpts for SupYLabel {
3904 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3905 self.opts.push((key, val).into());
3906 self
3907 }
3908}
3909
3910#[derive(Clone, Debug, PartialEq)]
3920pub struct Legend {
3921 pub opts: Vec<Opt>,
3923}
3924
3925impl Default for Legend {
3926 fn default() -> Self { Self::new() }
3927}
3928
3929impl Legend {
3930 pub fn new() -> Self {
3932 Self { opts: Vec::new() }
3933 }
3934}
3935
3936pub fn legend() -> Legend { Legend::new() }
3938
3939impl Matplotlib for Legend {
3940 fn is_prelude(&self) -> bool { false }
3941
3942 fn data(&self) -> Option<Value> { None }
3943
3944 fn py_cmd(&self) -> String {
3945 format!("ax.legend({})", self.opts.as_py())
3946 }
3947}
3948
3949impl MatplotlibOpts for Legend {
3950 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3951 self.opts.push((key, val).into());
3952 self
3953 }
3954}
3955
3956#[derive(Clone, Debug, PartialEq)]
3966pub struct Grid {
3967 pub onoff: bool,
3969 pub opts: Vec<Opt>,
3971}
3972
3973impl Grid {
3974 pub fn new(onoff: bool) -> Self { Self { onoff, opts: Vec::new() } }
3976}
3977
3978pub fn grid(onoff: bool) -> Grid { Grid::new(onoff) }
3980
3981impl Matplotlib for Grid {
3982 fn is_prelude(&self) -> bool { false }
3983
3984 fn data(&self) -> Option<Value> { None }
3985
3986 fn py_cmd(&self) -> String {
3987 format!("ax.grid({}, {})", self.onoff.as_py(), self.opts.as_py())
3988 }
3989}
3990
3991impl MatplotlibOpts for Grid {
3992 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
3993 self.opts.push((key, val).into());
3994 self
3995 }
3996}
3997
3998#[derive(Clone, Debug, PartialEq)]
4008pub struct TightLayout {
4009 pub opts: Vec<Opt>,
4011}
4012
4013impl Default for TightLayout {
4014 fn default() -> Self { Self::new() }
4015}
4016
4017impl TightLayout {
4018 pub fn new() -> Self { Self { opts: Vec::new() } }
4020}
4021
4022pub fn tight_layout() -> TightLayout { TightLayout::new() }
4024
4025impl Matplotlib for TightLayout {
4026 fn is_prelude(&self) -> bool { false }
4027
4028 fn data(&self) -> Option<Value> { None }
4029
4030 fn py_cmd(&self) -> String {
4031 format!("fig.tight_layout({})", self.opts.as_py())
4032 }
4033}
4034
4035impl MatplotlibOpts for TightLayout {
4036 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4037 self.opts.push((key, val).into());
4038 self
4039 }
4040}
4041
4042#[derive(Clone, Debug, PartialEq)]
4054pub struct InsetAxes {
4055 pub x: f64,
4057 pub y: f64,
4059 pub w: f64,
4061 pub h: f64,
4063 pub opts: Vec<Opt>,
4065}
4066
4067impl InsetAxes {
4068 pub fn new(x: f64, y: f64, w: f64, h: f64) -> Self {
4070 Self { x, y, w, h, opts: Vec::new() }
4071 }
4072
4073 pub fn new_pairs(xy: (f64, f64), wh: (f64, f64)) -> Self {
4076 Self { x: xy.0, y: xy.1, w: wh.0, h: wh.1, opts: Vec::new() }
4077 }
4078}
4079
4080pub fn inset_axes(x: f64, y: f64, w: f64, h: f64) -> InsetAxes {
4082 InsetAxes::new(x, y, w, h)
4083}
4084
4085pub fn inset_axes_pairs(xy: (f64, f64), wh: (f64, f64)) -> InsetAxes {
4088 InsetAxes::new_pairs(xy, wh)
4089}
4090
4091impl Matplotlib for InsetAxes {
4092 fn is_prelude(&self) -> bool { false }
4093
4094 fn data(&self) -> Option<Value> { None }
4095
4096 fn py_cmd(&self) -> String {
4097 format!("ax = ax.inset_axes([{}, {}, {}, {}]{}{})",
4098 self.x.as_py(),
4099 self.y.as_py(),
4100 self.w.as_py(),
4101 self.h.as_py(),
4102 if self.opts.is_empty() { "" } else { ", " },
4103 self.opts.as_py(),
4104 )
4105 }
4106}
4107
4108impl MatplotlibOpts for InsetAxes {
4109 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4110 self.opts.push((key, val).into());
4111 self
4112 }
4113}
4114
4115#[derive(Clone, Debug, PartialEq)]
4125pub struct Plot3 {
4126 pub x: Vec<f64>,
4128 pub y: Vec<f64>,
4130 pub z: Vec<f64>,
4132 pub opts: Vec<Opt>,
4134}
4135
4136impl Plot3 {
4137 pub fn new<X, Y, Z>(x: X, y: Y, z: Z) -> Self
4139 where
4140 X: IntoIterator<Item = f64>,
4141 Y: IntoIterator<Item = f64>,
4142 Z: IntoIterator<Item = f64>,
4143 {
4144 Self {
4145 x: x.into_iter().collect(),
4146 y: y.into_iter().collect(),
4147 z: z.into_iter().collect(),
4148 opts: Vec::new(),
4149 }
4150 }
4151
4152 pub fn new_data<I>(data: I) -> Self
4154 where I: IntoIterator<Item = (f64, f64, f64)>
4155 {
4156 let ((x, y), z) = data.into_iter().map(assoc).unzip();
4157 Self { x, y, z, opts: Vec::new() }
4158 }
4159}
4160
4161pub fn plot3<X, Y, Z>(x: X, y: Y, z: Z) -> Plot3
4163where
4164 X: IntoIterator<Item = f64>,
4165 Y: IntoIterator<Item = f64>,
4166 Z: IntoIterator<Item = f64>,
4167{
4168 Plot3::new(x, y, z)
4169}
4170
4171pub fn plot3_data<I>(data: I) -> Plot3
4173where I: IntoIterator<Item = (f64, f64, f64)>
4174{
4175 Plot3::new_data(data)
4176}
4177
4178impl Matplotlib for Plot3 {
4179 fn is_prelude(&self) -> bool { false }
4180
4181 fn data(&self) -> Option<Value> {
4182 let x: Vec<Value> =
4183 self.x.iter().copied().map(Value::from).collect();
4184 let y: Vec<Value> =
4185 self.y.iter().copied().map(Value::from).collect();
4186 let z: Vec<Value> =
4187 self.z.iter().copied().map(Value::from).collect();
4188 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
4189 }
4190
4191 fn py_cmd(&self) -> String {
4192 format!("ax.plot(data[0], data[1], data[2]{}{})",
4193 if self.opts.is_empty() { "" } else { ", " },
4194 self.opts.as_py(),
4195 )
4196 }
4197}
4198
4199impl MatplotlibOpts for Plot3 {
4200 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4201 self.opts.push((key, val).into());
4202 self
4203 }
4204}
4205
4206#[derive(Clone, Debug, PartialEq)]
4216pub struct Scatter3 {
4217 pub x: Vec<f64>,
4219 pub y: Vec<f64>,
4221 pub z: Vec<f64>,
4223 pub opts: Vec<Opt>,
4225}
4226
4227impl Scatter3 {
4228 pub fn new<X, Y, Z>(x: X, y: Y, z: Z) -> Self
4230 where
4231 X: IntoIterator<Item = f64>,
4232 Y: IntoIterator<Item = f64>,
4233 Z: IntoIterator<Item = f64>,
4234 {
4235 Self {
4236 x: x.into_iter().collect(),
4237 y: y.into_iter().collect(),
4238 z: z.into_iter().collect(),
4239 opts: Vec::new(),
4240 }
4241 }
4242
4243 pub fn new_data<I>(data: I) -> Self
4245 where I: IntoIterator<Item = (f64, f64, f64)>
4246 {
4247 let ((x, y), z) = data.into_iter().map(assoc).unzip();
4248 Self { x, y, z, opts: Vec::new() }
4249 }
4250}
4251
4252pub fn scatter3<X, Y, Z>(x: X, y: Y, z: Z) -> Scatter3
4254where
4255 X: IntoIterator<Item = f64>,
4256 Y: IntoIterator<Item = f64>,
4257 Z: IntoIterator<Item = f64>,
4258{
4259 Scatter3::new(x, y, z)
4260}
4261
4262pub fn scatter3_data<I>(data: I) -> Scatter3
4264where I: IntoIterator<Item = (f64, f64, f64)>
4265{
4266 Scatter3::new_data(data)
4267}
4268
4269impl Matplotlib for Scatter3 {
4270 fn is_prelude(&self) -> bool { false }
4271
4272 fn data(&self) -> Option<Value> {
4273 let x: Vec<Value> =
4274 self.x.iter().copied().map(Value::from).collect();
4275 let y: Vec<Value> =
4276 self.y.iter().copied().map(Value::from).collect();
4277 let z: Vec<Value> =
4278 self.z.iter().copied().map(Value::from).collect();
4279 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
4280 }
4281
4282 fn py_cmd(&self) -> String {
4283 format!("ax.scatter(data[0], data[1], data[2]{}{})",
4284 if self.opts.is_empty() { "" } else { ", " },
4285 self.opts.as_py(),
4286 )
4287 }
4288}
4289
4290impl MatplotlibOpts for Scatter3 {
4291 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4292 self.opts.push((key, val).into());
4293 self
4294 }
4295}
4296
4297#[derive(Clone, Debug, PartialEq)]
4307pub struct Quiver3 {
4308 pub x: Vec<f64>,
4310 pub y: Vec<f64>,
4312 pub z: Vec<f64>,
4314 pub vx: Vec<f64>,
4316 pub vy: Vec<f64>,
4318 pub vz: Vec<f64>,
4320 pub opts: Vec<Opt>,
4322}
4323
4324impl Quiver3 {
4325 pub fn new<X, Y, Z, VX, VY, VZ>(x: X, y: Y, z: Z, vx: VX, vy: VY, vz: VZ)
4327 -> Self
4328 where
4329 X: IntoIterator<Item = f64>,
4330 Y: IntoIterator<Item = f64>,
4331 Z: IntoIterator<Item = f64>,
4332 VX: IntoIterator<Item = f64>,
4333 VY: IntoIterator<Item = f64>,
4334 VZ: IntoIterator<Item = f64>,
4335 {
4336 Self {
4337 x: x.into_iter().collect(),
4338 y: y.into_iter().collect(),
4339 z: z.into_iter().collect(),
4340 vx: vx.into_iter().collect(),
4341 vy: vy.into_iter().collect(),
4342 vz: vz.into_iter().collect(),
4343 opts: Vec::new(),
4344 }
4345 }
4346
4347 pub fn new_triples<I, VI>(xyz: I, vxyz: VI) -> Self
4350 where
4351 I: IntoIterator<Item = (f64, f64, f64)>,
4352 VI: IntoIterator<Item = (f64, f64, f64)>,
4353 {
4354 let ((x, y), z) = xyz.into_iter().map(assoc).unzip();
4355 let ((vx, vy), vz) = vxyz.into_iter().map(assoc).unzip();
4356 Self { x, y, z, vx, vy, vz, opts: Vec::new() }
4357 }
4358
4359 pub fn new_data<I>(data: I) -> Self
4363 where I: IntoIterator<Item = (f64, f64, f64, f64, f64, f64)>
4364 {
4365 let (((((x, y), z), vx), vy), vz) = data.into_iter().map(assoc).unzip();
4366 Self { x, y, z, vx, vy, vz, opts: Vec::new() }
4367 }
4368}
4369
4370pub fn quiver3<X, Y, Z, VX, VY, VZ>(x: X, y: Y, z: Z, vx: VX, vy: VY, vz: VZ)
4372 -> Quiver3
4373where
4374 X: IntoIterator<Item = f64>,
4375 Y: IntoIterator<Item = f64>,
4376 Z: IntoIterator<Item = f64>,
4377 VX: IntoIterator<Item = f64>,
4378 VY: IntoIterator<Item = f64>,
4379 VZ: IntoIterator<Item = f64>,
4380{
4381 Quiver3::new(x, y, z, vx, vy, vz)
4382}
4383
4384pub fn quiver3_triples<I, VI>(xyz: I, vxyz: VI) -> Quiver3
4387where
4388 I: IntoIterator<Item = (f64, f64, f64)>,
4389 VI: IntoIterator<Item = (f64, f64, f64)>,
4390{
4391 Quiver3::new_triples(xyz, vxyz)
4392}
4393
4394pub fn quiver3_data<I>(data: I) -> Quiver3
4399where I: IntoIterator<Item = (f64, f64, f64, f64, f64, f64)>
4400{
4401 Quiver3::new_data(data)
4402}
4403
4404impl Matplotlib for Quiver3 {
4405 fn is_prelude(&self) -> bool { false }
4406
4407 fn data(&self) -> Option<Value> {
4408 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
4409 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
4410 let z: Vec<Value> = self.z.iter().copied().map(Value::from).collect();
4411 let vx: Vec<Value> = self.vx.iter().copied().map(Value::from).collect();
4412 let vy: Vec<Value> = self.vy.iter().copied().map(Value::from).collect();
4413 let vz: Vec<Value> = self.vz.iter().copied().map(Value::from).collect();
4414 Some(Value::Array(vec![
4415 x.into(), y.into(), z.into(), vx.into(), vy.into(), vz.into()]))
4416 }
4417
4418 fn py_cmd(&self) -> String {
4419 format!(
4420 "ax.quiver(\
4421 data[0], data[1], data[2], data[3], data[4], data[5]{}{})",
4422 if self.opts.is_empty() { "" } else { ", " },
4423 self.opts.as_py(),
4424 )
4425 }
4426}
4427
4428impl MatplotlibOpts for Quiver3 {
4429 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4430 self.opts.push((key, val).into());
4431 self
4432 }
4433}
4434
4435#[derive(Clone, Debug, PartialEq)]
4449pub struct Surface {
4450 pub x: Vec<Vec<f64>>,
4452 pub y: Vec<Vec<f64>>,
4454 pub z: Vec<Vec<f64>>,
4456 pub opts: Vec<Opt>,
4458}
4459
4460impl Surface {
4461 pub fn new<XI, XJ, YI, YJ, ZI, ZJ>(x: XI, y: YI, z: ZI) -> Self
4463 where
4464 XI: IntoIterator<Item = XJ>,
4465 XJ: IntoIterator<Item = f64>,
4466 YI: IntoIterator<Item = YJ>,
4467 YJ: IntoIterator<Item = f64>,
4468 ZI: IntoIterator<Item = ZJ>,
4469 ZJ: IntoIterator<Item = f64>,
4470 {
4471 let x: Vec<Vec<f64>> =
4472 x.into_iter()
4473 .map(|row| row.into_iter().collect())
4474 .collect();
4475 let y: Vec<Vec<f64>> =
4476 y.into_iter()
4477 .map(|row| row.into_iter().collect())
4478 .collect();
4479 let z: Vec<Vec<f64>> =
4480 z.into_iter()
4481 .map(|row| row.into_iter().collect())
4482 .collect();
4483 Self { x, y, z, opts: Vec::new() }
4484 }
4485
4486 pub fn new_flat<X, Y, Z>(x: X, y: Y, z: Z, rowlen: usize) -> Self
4491 where
4492 X: IntoIterator<Item = f64>,
4493 Y: IntoIterator<Item = f64>,
4494 Z: IntoIterator<Item = f64>,
4495 {
4496 if rowlen == 0 { panic!("row length cannot be zero"); }
4497 let x: Vec<Vec<f64>> =
4498 Chunks::new(x.into_iter(), rowlen)
4499 .collect();
4500 let y: Vec<Vec<f64>> =
4501 Chunks::new(y.into_iter(), rowlen)
4502 .collect();
4503 let z: Vec<Vec<f64>> =
4504 Chunks::new(z.into_iter(), rowlen)
4505 .collect();
4506 Self { x, y, z, opts: Vec::new() }
4507 }
4508
4509 pub fn new_data<I>(data: I, rowlen: usize) -> Self
4514 where I: IntoIterator<Item = (f64, f64, f64)>
4515 {
4516 if rowlen == 0 { panic!("row length cannot be zero"); }
4517 let mut x: Vec<Vec<f64>> = Vec::new();
4518 let mut y: Vec<Vec<f64>> = Vec::new();
4519 let mut z: Vec<Vec<f64>> = Vec::new();
4520 Chunks::new(data.into_iter(), rowlen)
4521 .for_each(|points| {
4522 let mut xi: Vec<f64> = Vec::with_capacity(rowlen);
4523 let mut yi: Vec<f64> = Vec::with_capacity(rowlen);
4524 let mut zi: Vec<f64> = Vec::with_capacity(rowlen);
4525 points.into_iter()
4526 .for_each(|(xij, yij, zij)| {
4527 xi.push(xij); yi.push(yij); zi.push(zij);
4528 });
4529 x.push(xi); y.push(yi); z.push(zi);
4530 });
4531 Self { x, y, z, opts: Vec::new() }
4532 }
4533}
4534
4535pub fn surface<XI, XJ, YI, YJ, ZI, ZJ>(x: XI, y: YI, z: ZI) -> Surface
4537where
4538 XI: IntoIterator<Item = XJ>,
4539 XJ: IntoIterator<Item = f64>,
4540 YI: IntoIterator<Item = YJ>,
4541 YJ: IntoIterator<Item = f64>,
4542 ZI: IntoIterator<Item = ZJ>,
4543 ZJ: IntoIterator<Item = f64>,
4544{
4545 Surface::new(x, y, z)
4546}
4547
4548pub fn surface_flat<X, Y, Z>(x: X, y: Y, z: Z, rowlen: usize) -> Surface
4553where
4554 X: IntoIterator<Item = f64>,
4555 Y: IntoIterator<Item = f64>,
4556 Z: IntoIterator<Item = f64>,
4557{
4558 Surface::new_flat(x, y, z, rowlen)
4559}
4560
4561pub fn surface_data<I>(data: I, rowlen: usize) -> Surface
4566where I: IntoIterator<Item = (f64, f64, f64)>
4567{
4568 Surface::new_data(data, rowlen)
4569}
4570
4571impl Matplotlib for Surface {
4572 fn is_prelude(&self) -> bool { false }
4573
4574 fn data(&self) -> Option<Value> {
4575 let x: Vec<Value> =
4576 self.x.iter()
4577 .map(|row| {
4578 let row: Vec<Value> =
4579 row.iter().copied().map(Value::from).collect();
4580 Value::Array(row)
4581 })
4582 .collect();
4583 let y: Vec<Value> =
4584 self.y.iter()
4585 .map(|row| {
4586 let row: Vec<Value> =
4587 row.iter().copied().map(Value::from).collect();
4588 Value::Array(row)
4589 })
4590 .collect();
4591 let z: Vec<Value> =
4592 self.z.iter()
4593 .map(|row| {
4594 let row: Vec<Value> =
4595 row.iter().copied().map(Value::from).collect();
4596 Value::Array(row)
4597 })
4598 .collect();
4599 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
4600 }
4601
4602 fn py_cmd(&self) -> String {
4603 format!("\
4604 ax.plot_surface(\
4605 np.array(data[0]), \
4606 np.array(data[1]), \
4607 np.array(data[2])\
4608 {}{})",
4609 if self.opts.is_empty() { "" } else { ", " },
4610 self.opts.as_py(),
4611 )
4612 }
4613}
4614
4615impl MatplotlibOpts for Surface {
4616 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4617 self.opts.push((key, val).into());
4618 self
4619 }
4620}
4621
4622#[derive(Clone, Debug, PartialEq)]
4632pub struct Trisurf {
4633 pub x: Vec<f64>,
4635 pub y: Vec<f64>,
4637 pub z: Vec<f64>,
4639 pub opts: Vec<Opt>,
4641}
4642
4643impl Trisurf {
4644 pub fn new<X, Y, Z>(x: X, y: Y, z: Z) -> Self
4646 where
4647 X: IntoIterator<Item = f64>,
4648 Y: IntoIterator<Item = f64>,
4649 Z: IntoIterator<Item = f64>,
4650 {
4651 Self {
4652 x: x.into_iter().collect(),
4653 y: y.into_iter().collect(),
4654 z: z.into_iter().collect(),
4655 opts: Vec::new(),
4656 }
4657 }
4658
4659 pub fn new_data<I>(data: I) -> Self
4661 where I: IntoIterator<Item = (f64, f64, f64)>
4662 {
4663 let ((x, y), z) = data.into_iter().map(assoc).unzip();
4664 Self { x, y, z, opts: Vec::new() }
4665 }
4666}
4667
4668pub fn trisurf<X, Y, Z>(x: X, y: Y, z: Z) -> Trisurf
4670where
4671 X: IntoIterator<Item = f64>,
4672 Y: IntoIterator<Item = f64>,
4673 Z: IntoIterator<Item = f64>,
4674{
4675 Trisurf::new(x, y, z)
4676}
4677
4678pub fn trisurf_data<I>(data: I) -> Trisurf
4680where I: IntoIterator<Item = (f64, f64, f64)>
4681{
4682 Trisurf::new_data(data)
4683}
4684
4685impl Matplotlib for Trisurf {
4686 fn is_prelude(&self) -> bool { false }
4687
4688 fn data(&self) -> Option<Value> {
4689 let x: Vec<Value> = self.x.iter().copied().map(Value::from).collect();
4690 let y: Vec<Value> = self.y.iter().copied().map(Value::from).collect();
4691 let z: Vec<Value> = self.z.iter().copied().map(Value::from).collect();
4692 Some(Value::Array(vec![x.into(), y.into(), z.into()]))
4693 }
4694
4695 fn py_cmd(&self) -> String {
4696 format!("ax.plot_trisurf(data[0], data[1], data[2]{}{})",
4697 if self.opts.is_empty() { "" } else { ", " },
4698 self.opts.as_py(),
4699 )
4700 }
4701}
4702
4703impl MatplotlibOpts for Trisurf {
4704 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4705 self.opts.push((key, val).into());
4706 self
4707 }
4708}
4709
4710#[derive(Clone, Debug, PartialEq)]
4722pub struct ViewInit {
4723 pub azim: f64,
4725 pub elev: f64,
4727 pub opts: Vec<Opt>,
4729}
4730
4731impl ViewInit {
4732 pub fn new(azim: f64, elev: f64) -> Self {
4734 Self { azim, elev, opts: Vec::new() }
4735 }
4736}
4737
4738pub fn view_init(azim: f64, elev: f64) -> ViewInit { ViewInit::new(azim, elev) }
4740
4741impl Matplotlib for ViewInit {
4742 fn is_prelude(&self) -> bool { false }
4743
4744 fn data(&self) -> Option<Value> { None }
4745
4746 fn py_cmd(&self) -> String {
4747 format!("ax.view_init(azim={}, elev={}{}{})",
4748 self.azim.as_py(),
4749 self.elev.as_py(),
4750 if self.opts.is_empty() { "" } else { ", " },
4751 self.opts.as_py(),
4752 )
4753 }
4754}
4755
4756impl MatplotlibOpts for ViewInit {
4757 fn kwarg<T: Into<PyValue>>(&mut self, key: &str, val: T) -> &mut Self {
4758 self.opts.push((key, val).into());
4759 self
4760 }
4761}
4762
4763pub trait Associator<P> {
4799 fn assoc(self) -> P;
4801}
4802
4803impl<A, B, C> Associator<((A, B), C)> for (A, B, C) {
4807 fn assoc(self) -> ((A, B), C) { ((self.0, self.1), self.2) }
4808}
4809
4810impl<A, B, C> Associator<(A, B, C)> for ((A, B), C) {
4811 fn assoc(self) -> (A, B, C) { (self.0.0, self.0.1, self.1) }
4812}
4813
4814impl<A, B, C> Associator<(A, (B, C))> for (A, B, C) {
4815 fn assoc(self) -> (A, (B, C)) { (self.0, (self.1, self.2)) }
4816}
4817
4818impl<A, B, C> Associator<(A, B, C)> for (A, (B, C)) {
4819 fn assoc(self) -> (A, B, C) { (self.0, self.1.0, self.1.1) }
4820}
4821
4822macro_rules! impl_biassoc {
4825 (
4826 <$( $gen:ident ),+>,
4827 $pair:ty,
4828 ($( $l:ident ),+),
4829 $r:ident $(,)?
4830 ) => {
4831 impl<$( $gen ),+> Associator<$pair> for ($( $gen ),+) {
4832 fn assoc(self) -> $pair {
4833 let ($( $l ),+, $r) = self;
4834 (($( $l ),+).assoc(), $r)
4835 }
4836 }
4837
4838 impl<$( $gen ),+> Associator<($( $gen ),+)> for $pair {
4839 fn assoc(self) -> ($( $gen ),+) {
4840 let ($( $l ),+) = self.0.assoc();
4841 ($( $l ),+, self.1)
4842 }
4843 }
4844 };
4845 (
4846 <$( $gen:ident ),+>,
4847 $pair:ty,
4848 $l:ident,
4849 ($( $r:ident ),+) $(,)?
4850 ) => {
4851 impl<$( $gen ),+> Associator<$pair> for ($( $gen ),+) {
4852 fn assoc(self) -> $pair {
4853 let ($l, $( $r ),+) = self;
4854 ($l, ($( $r ),+).assoc())
4855 }
4856 }
4857
4858 impl<$( $gen ),+> Associator<($( $gen ),+)> for $pair {
4859 fn assoc(self) -> ($( $gen ),+) {
4860 let ($( $r ),+) = self.1.assoc();
4861 (self.0, $( $r ),+)
4862 }
4863 }
4864 };
4865}
4866
4867impl_biassoc!(<A, B, C, D>, (((A, B), C), D), (a, b, c), d);
4868impl_biassoc!(<A, B, C, D>, ((A, (B, C)), D), (a, b, c), d);
4869impl_biassoc!(<A, B, C, D>, (A, ((B, C), D)), a, (b, c, d));
4870impl_biassoc!(<A, B, C, D>, (A, (B, (C, D))), a, (b, c, d));
4871impl_biassoc!(<A, B, C, D, E>, ((((A, B), C), D), E), (a, b, c, d), e);
4872impl_biassoc!(<A, B, C, D, E>, (((A, (B, C)), D), E), (a, b, c, d), e);
4873impl_biassoc!(<A, B, C, D, E>, ((A, ((B, C), D)), E), (a, b, c, d), e);
4874impl_biassoc!(<A, B, C, D, E>, ((A, (B, (C, D))), E), (a, b, c, d), e);
4875impl_biassoc!(<A, B, C, D, E>, (A, (((B, C), D), E)), a, (b, c, d, e));
4876impl_biassoc!(<A, B, C, D, E>, (A, ((B, (C, D)), E)), a, (b, c, d, e));
4877impl_biassoc!(<A, B, C, D, E>, (A, (B, ((C, D), E))), a, (b, c, d, e));
4878impl_biassoc!(<A, B, C, D, E>, (A, (B, (C, (D, E)))), a, (b, c, d, e));
4879impl_biassoc!(<A, B, C, D, E, F>, (((((A, B), C), D), E), F), (a, b, c, d, e), f);
4880impl_biassoc!(<A, B, C, D, E, F>, ((((A, (B, C)), D), E), F), (a, b, c, d, e), f);
4881impl_biassoc!(<A, B, C, D, E, F>, (((A, ((B, C), D)), E), F), (a, b, c, d, e), f);
4882impl_biassoc!(<A, B, C, D, E, F>, (((A, (B, (C, D))), E), F), (a, b, c, d, e), f);
4883impl_biassoc!(<A, B, C, D, E, F>, ((A, (((B, C), D), E)), F), (a, b, c, d, e), f);
4884impl_biassoc!(<A, B, C, D, E, F>, ((A, ((B, (C, D)), E)), F), (a, b, c, d, e), f);
4885impl_biassoc!(<A, B, C, D, E, F>, ((A, (B, ((C, D), E))), F), (a, b, c, d, e), f);
4886impl_biassoc!(<A, B, C, D, E, F>, ((A, (B, (C, (D, E)))), F), (a, b, c, d, e), f);
4887impl_biassoc!(<A, B, C, D, E, F>, (A, ((((B, C), D), E), F)), a, (b, c, d, e, f));
4888impl_biassoc!(<A, B, C, D, E, F>, (A, (((B, (C, D)), E), F)), a, (b, c, d, e, f));
4889impl_biassoc!(<A, B, C, D, E, F>, (A, ((B, ((C, D), E)), F)), a, (b, c, d, e, f));
4890impl_biassoc!(<A, B, C, D, E, F>, (A, ((B, (C, (D, E))), F)), a, (b, c, d, e, f));
4891impl_biassoc!(<A, B, C, D, E, F>, (A, (B, (((C, D), E), F))), a, (b, c, d, e, f));
4892impl_biassoc!(<A, B, C, D, E, F>, (A, (B, ((C, (D, E)), F))), a, (b, c, d, e, f));
4893impl_biassoc!(<A, B, C, D, E, F>, (A, (B, (C, ((D, E), F)))), a, (b, c, d, e, f));
4894impl_biassoc!(<A, B, C, D, E, F>, (A, (B, (C, (D, (E, F))))), a, (b, c, d, e, f));
4895
4896pub fn assoc<A, B>(a: A) -> B
4899where A: Associator<B>
4900{
4901 a.assoc()
4902}
4903
4904pub fn assoc_iter<I, J, A, B>(iter: I) -> std::iter::Map<J, fn(A) -> B>
4906where
4907 I: IntoIterator<IntoIter = J, Item = A>,
4908 J: Iterator<Item = A>,
4909 A: Associator<B>,
4910{
4911 iter.into_iter().map(assoc)
4912}
4913
4914#[cfg(test)]
4915mod tests {
4916 use crate::{ Mpl, Run, MatplotlibOpts, opt, GSPos };
4917 use super::*;
4918
4919 fn runner() -> Run { Run::Debug }
4920
4921 #[test]
4922 fn test_prelude_init() {
4923 Mpl::default()
4924 | runner()
4925 }
4926
4927 #[test]
4928 fn test_axhline() {
4929 Mpl::default()
4930 & axhline(10.0).o("linestyle", "-")
4931 | runner()
4932 }
4933
4934 #[test]
4935 fn test_axline() {
4936 Mpl::default()
4937 & axline((0.0, 0.0), (10.0, 10.0)).o("linestyle", "-")
4938 | runner()
4939 }
4940
4941 #[test]
4942 fn test_axlinem() {
4943 Mpl::default()
4944 & axlinem((0.0, 0.0), 1.0).o("linestyle", "-")
4945 | runner()
4946 }
4947
4948 #[test]
4949 fn test_axtext() {
4950 Mpl::default()
4951 & axtext(0.5, 0.5, "hello world").o("ha", "left").o("va", "bottom")
4952 | runner()
4953 }
4954
4955 #[test]
4956 fn test_axvline() {
4957 Mpl::default()
4958 & axvline(10.0).o("linestyle", "-")
4959 | runner()
4960 }
4961
4962 #[test]
4963 fn test_bar() {
4964 Mpl::default()
4965 & bar([0.0, 1.0], [0.5, 0.5]).o("color", "C0")
4966 | runner()
4967 }
4968
4969 #[test]
4970 fn test_bar_pairs() {
4971 Mpl::default()
4972 & bar_pairs([(0.0, 0.5), (1.0, 0.5)]).o("color", "C0")
4973 | runner()
4974 }
4975
4976 #[test]
4977 fn test_bar_eq() {
4978 assert_eq!(
4979 bar([0.0, 1.0], [0.5, 0.5]).o("color", "C0"),
4980 bar_pairs([(0.0, 0.5), (1.0, 0.5)]).o("color", "C0"),
4981 )
4982 }
4983
4984 #[test]
4985 fn test_barh() {
4986 Mpl::default()
4987 & barh([0.0, 1.0], [0.5, 0.5]).o("color", "C0")
4988 | runner()
4989 }
4990
4991 #[test]
4992 fn test_barh_pairs() {
4993 Mpl::default()
4994 & barh_pairs([(0.0, 0.5), (1.0, 0.5)]).o("color", "C0")
4995 | runner()
4996 }
4997
4998 #[test]
4999 fn test_barh_eq() {
5000 assert_eq!(
5001 barh([0.0, 1.0], [0.5, 0.5]).o("color", "C0"),
5002 barh_pairs([(0.0, 0.5), (1.0, 0.5)]).o("color", "C0"),
5003 )
5004 }
5005
5006 #[test]
5007 fn test_boxplot() {
5008 Mpl::default()
5009 & boxplot([[0.0, 1.0, 2.0], [2.0, 3.0, 4.0]]).o("notch", true)
5010 | runner()
5011 }
5012
5013 #[test]
5014 fn test_boxplot_flat() {
5015 Mpl::default()
5016 & boxplot_flat([0.0, 1.0, 2.0, 2.0, 3.0, 4.0], 3).o("notch", true)
5017 | runner()
5018 }
5019
5020 #[test]
5021 fn test_boxplot_eq() {
5022 assert_eq!(
5023 boxplot([[0.0, 1.0, 2.0], [2.0, 3.0, 4.0]]).o("notch", true),
5024 boxplot_flat([0.0, 1.0, 2.0, 2.0, 3.0, 4.0], 3).o("notch", true),
5025 )
5026 }
5027
5028 #[test]
5029 fn test_clabel() {
5030 Mpl::default()
5031 & imshow([[0.0, 1.0], [2.0, 3.0]])
5032 & colorbar()
5033 & clabel("hello world").o("fontsize", "medium")
5034 | runner()
5035 }
5036
5037 #[test]
5038 fn test_clim() {
5039 Mpl::default()
5040 & imshow([[0.0, 1.0], [2.0, 3.0]])
5041 & colorbar()
5042 & clim(Some(0.0), Some(1.0))
5043 | runner()
5044 }
5045
5046 #[test]
5047 fn test_colorbar() {
5048 Mpl::default()
5049 & imshow([[0.0, 1.0], [2.0, 3.0]])
5050 & colorbar().o("location", "top")
5051 | runner()
5052 }
5053
5054 #[test]
5055 fn test_contour() {
5056 Mpl::default()
5057 & contour([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
5058 .o("cmap", "bone")
5059 & colorbar()
5060 | runner()
5061 }
5062
5063 #[test]
5064 fn test_contour_flat() {
5065 Mpl::default()
5066 & contour_flat([0.0, 1.0], [0.0, 1.0], [0.0, 1.0, 2.0, 3.0])
5067 .o("cmap", "bone")
5068 & colorbar()
5069 | runner()
5070 }
5071
5072 #[test]
5073 fn test_contour_eq() {
5074 assert_eq!(
5075 contour([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
5076 .o("cmap", "bone"),
5077 contour_flat([0.0, 1.0], [0.0, 1.0], [0.0, 1.0, 2.0, 3.0])
5078 .o("cmap", "bone"),
5079 )
5080 }
5081
5082 #[test]
5083 fn test_contourf() {
5084 Mpl::default()
5085 & contour([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
5086 .o("cmap", "bone")
5087 & colorbar()
5088 | runner()
5089 }
5090
5091 #[test]
5092 fn test_contourf_flat() {
5093 Mpl::default()
5094 & contour_flat([0.0, 1.0], [0.0, 1.0], [0.0, 1.0, 2.0, 3.0])
5095 .o("cmap", "bone")
5096 & colorbar()
5097 | runner()
5098 }
5099
5100 #[test]
5101 fn test_contourf_eq() {
5102 assert_eq!(
5103 contourf([0.0, 1.0], [0.0, 1.0], [[0.0, 1.0], [2.0, 3.0]])
5104 .o("cmap", "bone"),
5105 contourf_flat([0.0, 1.0], [0.0, 1.0], [0.0, 1.0, 2.0, 3.0])
5106 .o("cmap", "bone"),
5107 )
5108 }
5109
5110 #[test]
5111 fn test_cticklabels() {
5112 Mpl::default()
5113 & imshow([[0.0, 1.0], [2.0, 3.0]])
5114 & colorbar()
5115 & cticklabels([0.0, 1.0], ["zero", "one"]).o("minor", true)
5116 | runner()
5117 }
5118
5119 #[test]
5120 fn test_cticklabels_data() {
5121 Mpl::default()
5122 & imshow([[0.0, 1.0], [2.0, 3.0]])
5123 & colorbar()
5124 & cticklabels_data([(0.0, "zero"), (1.0, "one")]).o("minor", true)
5125 | runner()
5126 }
5127
5128 #[test]
5129 fn test_cticklabels_eq() {
5130 assert_eq!(
5131 cticklabels([0.0, 1.0], ["zero", "one"]).o("minor", true),
5132 cticklabels_data([(0.0, "zero"), (1.0, "one")]).o("minor", true),
5133 )
5134 }
5135
5136 #[test]
5137 fn test_cticks() {
5138 Mpl::default()
5139 & imshow([[0.0, 1.0], [2.0, 3.0]])
5140 & colorbar()
5141 & cticks([0.0, 1.0])
5142 .o("labels", PyValue::list(["zero", "one"]))
5143 | runner()
5144 }
5145
5146 #[test]
5147 fn test_errorbar() {
5148 Mpl::default()
5149 & errorbar([0.0, 1.0], [0.0, 1.0], [0.5, 1.0]).o("color", "C0")
5150 | runner()
5151 }
5152
5153 #[test]
5154 fn test_errorbar_data() {
5155 Mpl::default()
5156 & errorbar_data([(0.0, 0.0, 0.5), (1.0, 1.0, 1.0)]).o("color", "C0")
5157 | runner()
5158 }
5159
5160 #[test]
5161 fn test_errorbar_eq() {
5162 assert_eq!(
5163 errorbar([0.0, 1.0], [0.0, 1.0], [0.5, 1.0]).o("color", "C0"),
5164 errorbar_data([(0.0, 0.0, 0.5), (1.0, 1.0, 1.0)]).o("color", "C0"),
5165 )
5166 }
5167
5168 #[test]
5169 fn test_errorbar2() {
5170 Mpl::default()
5171 & errorbar2([0.0, 1.0], [0.0, 1.0], [1.0, 0.5], [0.5, 1.0])
5172 .o("color", "C0")
5173 | runner()
5174 }
5175
5176 #[test]
5177 fn test_errorbar2_data() {
5178 Mpl::default()
5179 & errorbar2_data([(0.0, 0.0, 1.0, 0.5), (1.0, 1.0, 0.5, 1.0)])
5180 .o("color", "C0")
5181 | runner()
5182 }
5183
5184 #[test]
5185 fn test_errorbar2_eq() {
5186 assert_eq!(
5187 errorbar2([0.0, 1.0], [0.0, 1.0], [1.0, 0.5], [0.5, 1.0])
5188 .o("color", "C0"),
5189 errorbar2_data([(0.0, 0.0, 1.0, 0.5), (1.0, 1.0, 0.5, 1.0)])
5190 .o("color", "C0"),
5191 )
5192 }
5193
5194 #[test]
5195 fn test_figtext() {
5196 Mpl::default()
5197 & figtext(0.5, 0.5, "hello world").o("ha", "left").o("va", "bottom")
5198 | runner()
5199 }
5200
5201 #[test]
5202 fn test_fill_between() {
5203 Mpl::default()
5204 & fill_between([0.0, 1.0], [-0.5, 0.0], [0.5, 2.0]).o("color", "C0")
5205 | runner()
5206 }
5207
5208 #[test]
5209 fn test_fill_between_data() {
5210 Mpl::default()
5211 & fill_between_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)])
5212 .o("color", "C0")
5213 | runner()
5214 }
5215
5216 #[test]
5217 fn test_fill_between_eq() {
5218 assert_eq!(
5219 fill_between([0.0, 1.0], [-0.5, 0.0], [0.5, 2.0]).o("color", "C0"),
5220 fill_between_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)])
5221 .o("color", "C0"),
5222 )
5223 }
5224
5225 #[test]
5226 fn test_fillbetween_from_errorbar() {
5227 let ebar =
5228 errorbar_data([(0.0, 0.0, 0.5), (1.0, 1.0, 1.0)]);
5229 let ebar2 =
5230 errorbar2_data([(0.0, 0.25, 0.75, 0.25), (1.0, 1.0, 1.0, 1.0)]);
5231 let fbetw =
5232 fill_between_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)]);
5233 assert_eq!(FillBetween::from(ebar), fbetw);
5234 assert_eq!(FillBetween::from(ebar2), fbetw);
5235 }
5236
5237 #[test]
5238 fn test_errorbar_from_fillbetween() {
5239 let fbetw = fill_between_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)]);
5240 let ebar = errorbar_data([(0.0, 0.0, 0.5), (1.0, 1.0, 1.0)]);
5241 assert_eq!(Errorbar::from(fbetw), ebar);
5242 }
5243
5244 #[test]
5245 fn test_fill_betweenx() {
5246 Mpl::default()
5247 & fill_betweenx([0.0, 1.0], [-0.5, 0.0], [0.5, 2.0])
5248 .o("color", "C0")
5249 | runner()
5250 }
5251
5252 #[test]
5253 fn test_fill_betweenx_data() {
5254 Mpl::default()
5255 & fill_betweenx_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)])
5256 .o("color", "C0")
5257 | runner()
5258 }
5259
5260 #[test]
5261 fn test_fill_betweenx_eq() {
5262 assert_eq!(
5263 fill_betweenx([0.0, 1.0], [-0.5, 0.0], [0.5, 2.0]).o("color", "C0"),
5264 fill_betweenx_data([(0.0, -0.5, 0.5), (1.0, 0.0, 2.0)])
5265 .o("color", "C0"),
5266 )
5267 }
5268
5269 #[test]
5270 fn test_grid() {
5271 Mpl::default()
5272 & grid(true).o("which", "both")
5273 | runner()
5274 }
5275
5276 #[test]
5277 fn test_hist() {
5278 Mpl::default()
5279 & hist([0.0, 1.0, 2.0])
5280 .o("bins", PyValue::list([-0.5, 0.5, 1.5, 2.5]))
5281 | runner()
5282 }
5283
5284 #[test]
5285 fn test_hist2d() {
5286 Mpl::default()
5287 & hist2d([0.0, 1.0, 2.0], [0.0, 2.0, 4.0]).o("cmap", "bone")
5288 | runner()
5289 }
5290
5291 #[test]
5292 fn test_hist2d_pairs() {
5293 Mpl::default()
5294 & hist2d_pairs([(0.0, 0.0), (1.0, 2.0), (2.0, 4.0)])
5295 .o("cmap", "bone")
5296 | runner()
5297 }
5298
5299 #[test]
5300 fn test_hist2d_eq() {
5301 assert_eq!(
5302 hist2d([0.0, 1.0, 2.0], [0.0, 2.0, 4.0]).o("cmap", "bone"),
5303 hist2d_pairs([(0.0, 0.0), (1.0, 2.0), (2.0, 4.0)]).o("cmap", "bone"),
5304 )
5305 }
5306
5307 #[test]
5308 fn test_violinplot() {
5309 Mpl::default()
5310 & violinplot([[0.0, 1.0], [2.0, 3.0]]).o("vert", false)
5311 | runner()
5312 }
5313
5314 #[test]
5315 fn test_violinplot_flat() {
5316 Mpl::default()
5317 & violinplot_flat([0.0, 1.0, 2.0, 3.0], 2).o("vert", false)
5318 | runner()
5319 }
5320
5321 #[test]
5322 fn test_violinplot_eq() {
5323 assert_eq!(
5324 violinplot([[0.0, 1.0], [2.0, 3.0]]).o("vert", false),
5325 violinplot_flat([0.0, 1.0, 2.0, 3.0], 2).o("vert", false),
5326 )
5327 }
5328
5329 #[test]
5330 fn test_imshow() {
5331 Mpl::default()
5332 & imshow([[0.0, 1.0], [2.0, 3.0]]).o("cmap", "bone")
5333 | runner()
5334 }
5335
5336 #[test]
5337 fn test_imshow_flat() {
5338 Mpl::default()
5339 & imshow_flat([0.0, 1.0, 2.0, 3.0], 2).o("cmap", "bone")
5340 | runner()
5341 }
5342
5343 #[test]
5344 fn test_imshow_eq() {
5345 assert_eq!(
5346 imshow([[0.0, 1.0], [2.0, 3.0]]).o("cmap", "bone"),
5347 imshow_flat([0.0, 1.0, 2.0, 3.0], 2).o("cmap", "bone"),
5348 )
5349 }
5350
5351 #[test]
5352 fn test_inset_axes() {
5353 Mpl::default()
5354 & inset_axes(0.5, 0.5, 0.25, 0.25).o("polar", true)
5355 | runner()
5356 }
5357
5358 #[test]
5359 fn test_inset_axes_pairs() {
5360 Mpl::default()
5361 & inset_axes_pairs((0.5, 0.5), (0.25, 0.25)).o("polar", true)
5362 | runner()
5363 }
5364
5365 #[test]
5366 fn test_label() {
5367 Mpl::default()
5368 & label(Axis::X, "xlabel").o("fontsize", "large")
5369 & label(Axis::Y, "ylabel").o("fontsize", "large")
5370 | runner()
5371 }
5372
5373 #[test]
5374 fn test_xlabel() {
5375 Mpl::default()
5376 & xlabel("xlabel").o("fontsize", "large")
5377 | runner()
5378 }
5379
5380 #[test]
5381 fn test_ylabel() {
5382 Mpl::default()
5383 & ylabel("ylabel").o("fontsize", "large")
5384 | runner()
5385 }
5386
5387 #[test]
5388 fn test_label_eq() {
5389 assert_eq!(label(Axis::X, "xlabel"), xlabel("xlabel"));
5390 assert_eq!(label(Axis::Y, "ylabel"), ylabel("ylabel"));
5391 }
5392
5393 #[test]
5394 fn test_legend() {
5395 Mpl::default()
5396 & plot([0.0], [0.0]).o("label", "hello world")
5397 & legend().o("loc", "lower left")
5398 | runner()
5399 }
5400
5401 #[test]
5402 fn test_lim() {
5403 Mpl::default()
5404 & lim(Axis::X, Some(-10.0), Some(10.0))
5405 & lim(Axis::Y, Some(-10.0), Some(10.0))
5406 | runner()
5407 }
5408
5409 #[test]
5410 fn test_xlim() {
5411 Mpl::default()
5412 & xlim(Some(-10.0), Some(10.0))
5413 | runner()
5414 }
5415
5416 #[test]
5417 fn test_ylim() {
5418 Mpl::default()
5419 & ylim(Some(-10.0), Some(10.0))
5420 | runner()
5421 }
5422
5423 #[test]
5424 fn test_lim_eq() {
5425 assert_eq!(
5426 lim(Axis::X, Some(-10.0), Some(15.0)),
5427 xlim(Some(-10.0), Some(15.0)),
5428 );
5429 assert_eq!(
5430 lim(Axis::Y, Some(-10.0), Some(15.0)),
5431 ylim(Some(-10.0), Some(15.0)),
5432 );
5433 assert_eq!(
5434 lim(Axis::Z, Some(-10.0), Some(15.0)),
5435 zlim(Some(-10.0), Some(15.0)),
5436 )
5437 }
5438
5439 #[test]
5440 fn test_pie() {
5441 Mpl::default()
5442 & pie([1.0, 2.0]).o("radius", 2)
5443 | runner()
5444 }
5445
5446 #[test]
5447 fn test_plot() {
5448 Mpl::default()
5449 & plot([0.0, 1.0], [0.0, 1.0]).o("color", "C0")
5450 | runner()
5451 }
5452
5453 #[test]
5454 fn test_plot_pairs() {
5455 Mpl::default()
5456 & plot_pairs([(0.0, 0.0), (1.0, 1.0)]).o("color", "C0")
5457 | runner()
5458 }
5459
5460 #[test]
5461 fn test_plot_eq() {
5462 assert_eq!(
5463 plot([0.0, 1.0], [0.0, 1.0]).o("color", "C0"),
5464 plot_pairs([(0.0, 0.0), (1.0, 1.0)]).o("color", "C0"),
5465 )
5466 }
5467
5468 #[test]
5469 fn test_quiver() {
5470 Mpl::default()
5471 & quiver([0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0])
5472 .o("pivot", "middle")
5473 | runner()
5474 }
5475
5476 #[test]
5477 fn test_quiver_data() {
5478 Mpl::default()
5479 & quiver_data([(0.0, 0.0, 0.0, 0.0), (1.0, 1.0, 1.0, 1.0)])
5480 .o("pivot", "middle")
5481 | runner()
5482 }
5483
5484 #[test]
5485 fn test_quiver_pairs() {
5486 Mpl::default()
5487 & quiver_pairs([(0.0, 0.0), (1.0, 1.0)], [(0.0, 0.0), (1.0, 1.0)])
5488 .o("pivot", "middle")
5489 | runner()
5490 }
5491
5492 #[test]
5493 fn test_quiver_eq() {
5494 let norm =
5495 quiver([0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0])
5496 .o("pivot", "middle");
5497 let data =
5498 quiver_data([(0.0, 0.0, 0.0, 0.0), (1.0, 1.0, 1.0, 1.0)])
5499 .o("pivot", "middle");
5500 let pairs =
5501 quiver_pairs([(0.0, 0.0), (1.0, 1.0)], [(0.0, 0.0), (1.0, 1.0)])
5502 .o("pivot", "middle");
5503 assert_eq!(norm, data);
5504 assert_eq!(norm, pairs);
5505 }
5506
5507 #[test]
5508 fn test_rcparam() {
5509 Mpl::default()
5510 & rcparam("figure.figsize", PyValue::list([2.5, 3.5]))
5511 | runner()
5512 }
5513
5514 #[test]
5515 fn test_scale() {
5516 Mpl::default()
5517 & scale(Axis::X, AxisScale::Log)
5518 & scale(Axis::Y, AxisScale::Logit)
5519 | runner()
5520 }
5521
5522 #[test]
5523 fn test_xscale() {
5524 Mpl::default()
5525 & xscale(AxisScale::Log)
5526 | runner()
5527 }
5528
5529 #[test]
5530 fn test_yscale() {
5531 Mpl::default()
5532 & yscale(AxisScale::Logit)
5533 | runner()
5534 }
5535
5536 #[test]
5537 fn test_scale_eq() {
5538 assert_eq!(scale(Axis::X, AxisScale::Log), xscale(AxisScale::Log));
5539 assert_eq!(scale(Axis::Y, AxisScale::Logit), yscale(AxisScale::Logit));
5540 assert_eq!(scale(Axis::Z, AxisScale::SymLog), zscale(AxisScale::SymLog));
5541 }
5542
5543 #[test]
5544 fn test_scatter() {
5545 Mpl::default()
5546 & scatter([0.0, 1.0], [0.0, 1.0]).o("marker", "D")
5547 | runner()
5548 }
5549
5550 #[test]
5551 fn test_scatter_pairs() {
5552 Mpl::default()
5553 & scatter_pairs([(0.0, 0.0), (1.0, 1.0)]).o("marker", "D")
5554 | runner()
5555 }
5556
5557 #[test]
5558 fn test_scatter_eq() {
5559 assert_eq!(
5560 scatter([0.0, 1.0], [0.0, 1.0]).o("marker", "D"),
5561 scatter_pairs([(0.0, 0.0), (1.0, 1.0)]).o("marker", "D"),
5562 )
5563 }
5564
5565 #[test]
5566 fn test_suptitle() {
5567 Mpl::default()
5568 & suptitle("hello world").o("fontsize", "xx-small")
5569 | runner()
5570 }
5571
5572 #[test]
5573 fn test_supxlabel() {
5574 Mpl::default()
5575 & supxlabel("hello world").o("fontsize", "xx-small")
5576 | runner()
5577 }
5578
5579 #[test]
5580 fn test_supylabel() {
5581 Mpl::default()
5582 & supylabel("hello world").o("fontsize", "xx-small")
5583 | runner()
5584 }
5585
5586 #[test]
5587 fn test_make_grid() {
5588 Mpl::new_grid(3, 3, [opt("sharex", true), opt("sharey", true)])
5589 & focus_ax("AX[1, 1]")
5590 & plot([0.0, 1.0], [0.0, 1.0]).o("color", "C1")
5591 | runner()
5592 }
5593
5594 #[test]
5595 fn test_make_gridspec() {
5596 Mpl::new_gridspec(
5610 [
5611 opt("nrows", 3),
5612 opt("ncols", 3),
5613 opt("width_ratios", PyValue::list([1, 1, 2])),
5614 ],
5615 [
5616 GSPos::new(0..2, 0..2),
5617 GSPos::new(2..3, 0..2).sharex(Some(0)),
5618 GSPos::new(0..3, 2..3),
5619 ],
5620 )
5621 & focus_ax("AX[1]")
5622 & plot([0.0, 1.0], [0.0, 1.0]).o("color", "C1")
5623 | runner()
5624 }
5625
5626 #[test]
5627 fn test_tex_off() {
5628 Mpl::default()
5629 & tex_off()
5630 | runner()
5631 }
5632
5633 #[test]
5634 fn test_tex_on() {
5635 Mpl::default()
5636 & tex_on()
5637 | runner()
5638 }
5639
5640 #[test]
5641 fn test_text() {
5642 Mpl::default()
5643 & text(0.5, 0.5, "hello world").o("fontsize", "large")
5644 | runner()
5645 }
5646
5647 #[test]
5648 fn test_tick_params() {
5649 Mpl::default()
5650 & tick_params(Axis2::Both).o("color", "r")
5651 | runner()
5652 }
5653
5654 #[test]
5655 fn test_xtick_params() {
5656 Mpl::default()
5657 & xtick_params().o("color", "r")
5658 | runner()
5659 }
5660
5661 #[test]
5662 fn test_ytick_params() {
5663 Mpl::default()
5664 & xtick_params().o("color", "r")
5665 | runner()
5666 }
5667
5668 #[test]
5669 fn test_tick_params_eq() {
5670 assert_eq!(
5671 tick_params(Axis2::X).o("color", "r"),
5672 xtick_params().o("color", "r"),
5673 );
5674 assert_eq!(
5675 tick_params(Axis2::Y).o("color", "r"),
5676 ytick_params().o("color", "r"),
5677 );
5678 }
5679
5680 #[test]
5681 fn test_ticklabels() {
5682 Mpl::default()
5683 & ticklabels(Axis::X, [0.0, 1.0], ["x:zero", "x:one"])
5684 .o("fontsize", "small")
5685 & ticklabels(Axis::Y, [0.0, 1.0], ["y:zero", "y:one"])
5686 .o("fontsize", "small")
5687 | runner()
5688 }
5689
5690 #[test]
5691 fn test_ticklabels_data() {
5692 Mpl::default()
5693 & ticklabels_data(Axis::X, [(0.0, "x:zero"), (1.0, "x:one")])
5694 .o("fontsize", "small")
5695 & ticklabels_data(Axis::Y, [(0.0, "y:zero"), (1.0, "y:one")])
5696 .o("fontsize", "small")
5697 | runner()
5698 }
5699
5700 #[test]
5701 fn test_xticklabels() {
5702 Mpl::default()
5703 & xticklabels([0.0, 1.0], ["x:zero", "x:one"])
5704 .o("fontsize", "small")
5705 | runner()
5706 }
5707
5708 #[test]
5709 fn test_xticklabels_data() {
5710 Mpl::default()
5711 & xticklabels_data([(0.0, "x:zero"), (1.0, "x:one")])
5712 .o("fontsize", "small")
5713 | runner()
5714 }
5715
5716 #[test]
5717 fn test_yticklabels() {
5718 Mpl::default()
5719 & yticklabels([0.0, 1.0], ["y:zero", "y:one"])
5720 .o("fontsize", "small")
5721 | runner()
5722 }
5723
5724 #[test]
5725 fn test_yticklabels_data() {
5726 Mpl::default()
5727 & yticklabels_data([(0.0, "y:zero"), (1.0, "y:one")])
5728 .o("fontsize", "small")
5729 | runner()
5730 }
5731
5732 #[test]
5733 fn test_ticklabels_eq() {
5734 let normx =
5735 ticklabels(Axis::X, [0.0, 1.0], ["x:zero", "x:one"]);
5736 let normx_data =
5737 ticklabels_data(Axis::X, [(0.0, "x:zero"), (1.0, "x:one")]);
5738 let aliasx =
5739 xticklabels([0.0, 1.0], ["x:zero", "x:one"]);
5740 let aliasx_data =
5741 xticklabels_data([(0.0, "x:zero"), (1.0, "x:one")]);
5742 let normy =
5743 ticklabels(Axis::Y, [0.0, 1.0], ["y:zero", "y:one"]);
5744 let normy_data =
5745 ticklabels_data(Axis::Y, [(0.0, "y:zero"), (1.0, "y:one")]);
5746 let aliasy =
5747 yticklabels([0.0, 1.0], ["y:zero", "y:one"]);
5748 let aliasy_data =
5749 yticklabels_data([(0.0, "y:zero"), (1.0, "y:one")]);
5750 assert_eq!(normx, normx_data);
5751 assert_eq!(aliasx, aliasx_data);
5752 assert_eq!(normx, aliasx);
5753 assert_eq!(normy, normy_data);
5754 assert_eq!(aliasy, aliasy_data);
5755 assert_eq!(normy, aliasy);
5756 }
5757
5758 #[test]
5759 fn test_ticks() {
5760 Mpl::default()
5761 & ticks(Axis::X, [0.0, 1.0]).o("minor", true)
5762 & ticks(Axis::Y, [0.0, 2.0]).o("minor", true)
5763 | runner()
5764 }
5765
5766 #[test]
5767 fn test_xticks() {
5768 Mpl::default()
5769 & xticks([0.0, 1.0]).o("minor", true)
5770 | runner()
5771 }
5772
5773 #[test]
5774 fn test_yticks() {
5775 Mpl::default()
5776 & yticks([0.0, 2.0]).o("minor", true)
5777 | runner()
5778 }
5779
5780 #[test]
5781 fn test_ticks_eq() {
5782 let normx = ticks(Axis::X, [0.0, 1.0]);
5783 let aliasx = xticks([0.0, 1.0]);
5784 let normy = ticks(Axis::Y, [0.0, 2.0]);
5785 let aliasy = yticks([0.0, 2.0]);
5786 assert_eq!(normx, aliasx);
5787 assert_eq!(normy, aliasy);
5788 }
5789
5790 #[test]
5791 fn test_title() {
5792 Mpl::default()
5793 & title("hello world").o("fontsize", "large")
5794 | runner()
5795 }
5796
5797 #[test]
5798 fn test_tight_layout() {
5799 Mpl::new_grid(3, 3, [])
5800 & tight_layout().o("h_pad", 1.0).o("w_pad", 0.5)
5801 | runner()
5802 }
5803
5804 #[test]
5805 fn test_make_3d() {
5806 Mpl::new_3d([opt("elev", 50.0)])
5807 | runner()
5808 }
5809
5810 #[test]
5811 fn test_plot3() {
5812 Mpl::new_3d([])
5813 & plot3([0.0, 1.0], [0.0, 1.0], [0.0, 1.0]).o("marker", "D")
5814 | runner()
5815 }
5816
5817 #[test]
5818 fn test_plot3_data() {
5819 Mpl::new_3d([])
5820 & plot3_data([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]).o("marker", "D")
5821 | runner()
5822 }
5823
5824 #[test]
5825 fn test_plot3_eq() {
5826 assert_eq!(
5827 plot3([0.0, 1.0], [0.0, 1.0], [0.0, 1.0]).o("marker", "D"),
5828 plot3_data([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]).o("marker", "D"),
5829 )
5830 }
5831
5832 #[test]
5833 fn test_scatter3() {
5834 Mpl::new_3d([])
5835 & scatter3([0.0, 1.0], [0.0, 1.0], [0.0, 1.0]).o("marker", "D")
5836 | runner()
5837 }
5838
5839 #[test]
5840 fn test_scatter3_data() {
5841 Mpl::new_3d([])
5842 & scatter3_data([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]).o("marker", "D")
5843 | runner()
5844 }
5845
5846 #[test]
5847 fn test_scatter3_eq() {
5848 assert_eq!(
5849 scatter3([0.0, 1.0], [0.0, 1.0], [0.0, 1.0]).o("marker", "D"),
5850 scatter3_data([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]).o("marker", "D"),
5851 )
5852 }
5853
5854 #[test]
5855 fn test_quiver3() {
5856 Mpl::new_3d([])
5857 & quiver3(
5858 [0.0, 1.0],
5859 [0.0, 1.0],
5860 [0.0, 1.0],
5861 [1.0, 2.0],
5862 [1.0, 2.0],
5863 [1.0, 2.0],
5864 ).o("pivot", "middle")
5865 | runner()
5866 }
5867
5868 #[test]
5869 fn test_quiver3_data() {
5870 Mpl::new_3d([])
5871 & quiver3_data([
5872 (0.0, 0.0, 0.0, 1.0, 1.0, 1.0),
5873 (1.0, 1.0, 1.0, 2.0, 2.0, 2.0),
5874 ]).o("pivot", "middle")
5875 | runner()
5876 }
5877
5878 #[test]
5879 fn test_quiver3_triples() {
5880 Mpl::new_3d([])
5881 & quiver3_triples(
5882 [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
5883 [(1.0, 1.0, 1.0), (2.0, 2.0, 2.0)],
5884 ).o("pivot", "middle")
5885 | runner()
5886 }
5887
5888 #[test]
5889 fn test_quiver3_eq() {
5890 let norm = quiver3(
5891 [0.0, 1.0],
5892 [0.0, 1.0],
5893 [0.0, 1.0],
5894 [1.0, 2.0],
5895 [1.0, 2.0],
5896 [1.0, 2.0],
5897 ).o("pivot", "middle");
5898 let data = quiver3_data([
5899 (0.0, 0.0, 0.0, 1.0, 1.0, 1.0),
5900 (1.0, 1.0, 1.0, 2.0, 2.0, 2.0),
5901 ]).o("pivot", "middle");
5902 let triples = quiver3_triples(
5903 [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
5904 [(1.0, 1.0, 1.0), (2.0, 2.0, 2.0)],
5905 ).o("pivot", "middle");
5906 assert_eq!(norm, data);
5907 assert_eq!(norm, triples);
5908 }
5909
5910 #[test]
5911 fn test_surface() {
5912 Mpl::new_3d([])
5913 & surface(
5914 [[0.0, 1.0], [0.0, 1.0]],
5915 [[0.0, 0.0], [1.0, 1.0]],
5916 [[0.0, 1.0], [2.0, 3.0]],
5917 ).o("cmap", "rainbow")
5918 | runner()
5919 }
5920
5921 #[test]
5922 fn test_surface_data() {
5923 Mpl::new_3d([])
5924 & surface_data(
5925 [
5926 (0.0, 0.0, 0.0),
5927 (1.0, 0.0, 1.0),
5928 (0.0, 1.0, 2.0),
5929 (1.0, 1.0, 3.0),
5930 ],
5931 2,
5932 ).o("cmap", "rainbow")
5933 | runner()
5934 }
5935
5936 #[test]
5937 fn test_surface_flat() {
5938 Mpl::new_3d([])
5939 & surface_flat(
5940 [0.0, 1.0, 0.0, 1.0],
5941 [0.0, 0.0, 1.0, 1.0],
5942 [0.0, 1.0, 2.0, 3.0],
5943 2,
5944 ).o("cmap", "rainbow")
5945 | runner()
5946 }
5947
5948 #[test]
5949 fn test_surface_eq() {
5950 let norm = surface(
5951 [[0.0, 1.0], [0.0, 1.0]],
5952 [[0.0, 0.0], [1.0, 1.0]],
5953 [[0.0, 1.0], [2.0, 3.0]],
5954 ).o("cmap", "rainbow");
5955 let data = surface_data(
5956 [
5957 (0.0, 0.0, 0.0),
5958 (1.0, 0.0, 1.0),
5959 (0.0, 1.0, 2.0),
5960 (1.0, 1.0, 3.0),
5961 ],
5962 2,
5963 ).o("cmap", "rainbow");
5964 let flat = surface_flat(
5965 [0.0, 1.0, 0.0, 1.0],
5966 [0.0, 0.0, 1.0, 1.0],
5967 [0.0, 1.0, 2.0, 3.0],
5968 2,
5969 ).o("cmap", "rainbow");
5970 assert_eq!(norm, data);
5971 assert_eq!(norm, flat);
5972 }
5973
5974 #[test]
5975 fn test_trisurf() {
5976 Mpl::new_3d([])
5977 & trisurf(
5978 [0.0, 1.0, 0.0, 1.0],
5979 [0.0, 0.0, 1.0, 1.0],
5980 [0.0, 1.0, 2.0, 3.0],
5981 ).o("cmap", "rainbow")
5982 | runner()
5983 }
5984
5985 #[test]
5986 fn test_trisurf_data() {
5987 Mpl::new_3d([])
5988 & trisurf_data([
5989 (0.0, 0.0, 0.0),
5990 (1.0, 0.0, 1.0),
5991 (0.0, 1.0, 2.0),
5992 (1.0, 1.0, 3.0),
5993 ]).o("cmap", "rainbow")
5994 | runner()
5995 }
5996
5997 #[test]
5998 fn test_trisurf_eq() {
5999 let norm = trisurf(
6000 [0.0, 1.0, 0.0, 1.0],
6001 [0.0, 0.0, 1.0, 1.0],
6002 [0.0, 1.0, 2.0, 3.0],
6003 ).o("cmap", "rainbow");
6004 let data = trisurf_data([
6005 (0.0, 0.0, 0.0),
6006 (1.0, 0.0, 1.0),
6007 (0.0, 1.0, 2.0),
6008 (1.0, 1.0, 3.0),
6009 ]).o("cmap", "rainbow");
6010 assert_eq!(norm, data);
6011 }
6012
6013 #[test]
6014 fn test_view_init() {
6015 Mpl::new_3d([])
6016 & view_init(90.0, 0.0).o("roll", 45.0)
6017 | runner()
6018 }
6019
6020 #[test]
6021 fn test_zlabel() {
6022 Mpl::new_3d([])
6023 & zlabel("zlabel")
6024 | runner()
6025 }
6026
6027 #[test]
6028 fn test_zlim() {
6029 Mpl::new_3d([])
6030 & zlim(Some(-10.0), Some(15.0))
6031 | runner()
6032 }
6033
6034 #[test]
6035 fn test_zscale() {
6036 Mpl::new_3d([])
6037 & zscale(AxisScale::Log)
6038 | runner()
6039 }
6040
6041 #[test]
6042 fn test_zticklabels() {
6043 Mpl::new_3d([])
6044 & zticklabels([0.0, 1.0], ["zero", "one"]).o("minor", true)
6045 | runner()
6046 }
6047
6048 #[test]
6049 fn test_zticklabels_data() {
6050 Mpl::new_3d([])
6051 & zticklabels_data([(0.0, "zero"), (1.0, "one")]).o("minor", true)
6052 | runner()
6053 }
6054
6055 #[test]
6056 fn test_zticklabels_eq() {
6057 assert_eq!(
6058 zticklabels([0.0, 1.0], ["zero", "one"]).o("minor", true),
6059 zticklabels_data([(0.0, "zero"), (1.0, "one")]).o("minor", true),
6060 )
6061 }
6062
6063 #[test]
6064 fn test_zticks() {
6065 Mpl::new_3d([])
6066 & zticks([0.0, 1.0]).o("minor", true)
6067 | runner()
6068 }
6069}
6070