gnuplot/
axes_common.rs1// Copyright (c) 2013-2014 by SiegeLord
2//
3// All rights reserved. Distributed under LGPL 3.0. For full terms see the file LICENSE.
4
5use self::DataSourceType::*;
6
7pub use self::LabelType::*;
8pub use self::PlotType::*;
9use crate::coordinates::*;
10
11use crate::datatype::*;
12use crate::options::*;
13use crate::util::{escape, OneWayOwned};
14use crate::writer::*;
15use crate::ColorType;
16use std::borrow::Borrow;
17use std::fs;
18use std::path;
19
20pub struct PlotElement
21{
22 data: Vec<f64>,
23 num_rows: usize,
24 num_cols: usize,
25 plot_type: PlotType,
26 source_type: DataSourceType,
27 is_3d: bool,
28 options: Vec<PlotOption<String>>,
29}
30
31impl PlotElement
32{
33 pub fn new_plot(
34 plot_type: PlotType, data: Vec<f64>, num_rows: usize, num_cols: usize,
35 options: &[PlotOption<&str>],
36 ) -> PlotElement
37 {
38 PlotElement {
39 data,
40 num_rows,
41 num_cols,
42 plot_type,
43 source_type: Record,
44 is_3d: false,
45 options: options.to_one_way_owned(),
46 }
47 }
48
49 pub fn new_plot_matrix<T: DataType, X: IntoIterator<Item = T>>(
50 plot_type: PlotType, is_3d: bool, mat: X, num_rows: usize, num_cols: usize,
51 dimensions: Option<(f64, f64, f64, f64)>, options: Vec<PlotOption<String>>,
52 ) -> PlotElement
53 {
54 let mut count = 0;
55 let mut data = vec![];
56 // TODO: Reserve.
57 for x in mat
58 {
59 data.push(x.get());
60 count += 1;
61 }
62
63 if count < num_rows * num_cols
64 {
65 data.resize(num_rows * num_cols, f64::NAN);
66 }
67
68 let source_type = match dimensions
69 {
70 Some((x1, y1, x2, y2)) => SizedArray(x1, y1, x2, y2),
71 None => Array,
72 };
73
74 PlotElement {
75 data,
76 num_rows,
77 num_cols,
78 plot_type,
79 source_type,
80 is_3d,
81 options,
82 }
83 }
84
85 fn write_args(&self, source: &str, writer: &mut dyn Writer, version: GnuplotVersion)
86 {
87 let options = &self.options;
88 match self.source_type
89 {
90 Record =>
91 {
92 write!(
93 writer,
94 r#" "{}" binary endian=little record={} format="%float64" using "#,
95 source, self.num_rows
96 );
97
98 let mut col_idx = 1;
99 while col_idx < self.num_cols + 1
100 {
101 write!(writer, "{}", col_idx);
102 if col_idx < self.num_cols
103 {
104 writer.write_str(":");
105 }
106 col_idx += 1;
107 }
108 }
109 _ =>
110 {
111 write!(
112 writer,
113 r#" "{}" binary endian=little array=({},{}) format="%float64" "#,
114 source, self.num_cols, self.num_rows
115 );
116
117 if let SizedArray(x1, y1, x2, y2) = self.source_type
118 {
119 let (x1, x2) = if x1 > x2 { (x2, x1) } else { (x1, x2) };
120
121 let (y1, y2) = if y1 > y2 { (y2, y1) } else { (y1, y2) };
122 write!(writer, "origin=({:.12e},{:.12e}", x1, y1);
123 if self.is_3d
124 {
125 write!(writer, ",0");
126 }
127 write!(writer, ") ");
128 if self.num_cols > 1
129 {
130 write!(
131 writer,
132 "dx={:.12e} ",
133 (x2 - x1) / (self.num_cols as f64 - 1.0)
134 );
135 }
136 else
137 {
138 write!(writer, "dx=1 ");
139 }
140 if self.num_rows > 1
141 {
142 write!(
143 writer,
144 "dy={:.12e} ",
145 (y2 - y1) / (self.num_rows as f64 - 1.0)
146 );
147 }
148 else
149 {
150 write!(writer, "dy=1 ");
151 }
152 }
153 }
154 }
155
156 writer.write_str(" with ");
157 let type_str = match self.plot_type
158 {
159 Lines => "lines",
160 Points => "points",
161 LinesPoints => "linespoints",
162 XErrorLines => "xerrorlines",
163 YErrorLines => "yerrorlines",
164 XErrorBars => "xerrorbars",
165 YErrorBars => "yerrorbars",
166 XYErrorBars => "xyerrorbars",
167 FillBetween => "filledcurves",
168 Polygons => "polygons",
169 Boxes => "boxes",
170 BoxAndWhisker => "candlestick",
171 BoxXYError => "boxxyerror",
172 BoxErrorBars => "boxerrorbars",
173 Pm3D => "pm3d",
174 Image => "image",
175 };
176 writer.write_str(type_str);
177
178 if self.plot_type.is_fill()
179 {
180 if let FillBetween = self.plot_type
181 {
182 first_opt! {options,
183 FillRegion(d) =>
184 {
185 match d
186 {
187 Above => {writer.write_str(" above");},
188 Below => {writer.write_str(" below");},
189 Between => (), // This is the default behavior.
190 }
191 }
192 }
193 }
194
195 writer.write_str(" fill ");
196
197 let mut is_pattern = false;
198 first_opt! {self.options,
199 FillPattern(pattern_opt) =>
200 {
201 is_pattern = true;
202 writer.write_str("pattern ");
203 if let Fix(val) = pattern_opt
204 {
205 write!(writer, "{}", val as i32);
206 }
207 }
208 }
209
210 if !is_pattern
211 {
212 let mut color_has_alpha = false;
213 first_opt! {self.options,
214 Color(ref c) => {
215 color_has_alpha = c.has_alpha()
216 }
217 }
218 if !color_has_alpha
219 {
220 writer.write_str("transparent ");
221 }
222 writer.write_str("solid");
223 let mut alpha = 1.;
224 first_opt! {self.options,
225 FillAlpha(a) =>
226 {
227 alpha = a;
228 }
229 }
230 write!(writer, " {:.12e}", alpha);
231 }
232
233 if self.plot_type.is_line()
234 {
235 // Write this unconditionally so the write_line_options work below.
236 writer.write_str(" border ");
237 first_opt! {self.options,
238 BorderColor(ref s) =>
239 {
240 writer.write_str(&s.command());
241 }
242 }
243 }
244 else
245 {
246 writer.write_str(" noborder");
247 }
248 }
249
250 if self.plot_type.is_line()
251 {
252 AxesCommonData::write_line_options(writer, options, version);
253 }
254
255 if self.plot_type.is_points()
256 {
257 first_opt! {self.options,
258 PointSymbol(s) =>
259 {
260 write!(writer, " pt {}", char_to_symbol(s));
261 }
262 }
263
264 first_opt! {self.options,
265 PointSize(z) =>
266 {
267 write!(writer, " ps {}", z);
268 }
269 }
270 }
271
272 AxesCommonData::write_color_options(writer, &self.options, self.plot_type.is_fill(), None);
273
274 writer.write_str(" t \"");
275 first_opt! {self.options,
276 Caption(ref s) =>
277 {
278 writer.write_str(&escape(s));
279 }
280 }
281 writer.write_str("\"");
282
283 first_opt! {self.options,
284 WhiskerBars(f) =>
285 {
286 write!(writer, " whiskerbars {}", f);
287 }
288 }
289
290 first_opt! {self.options,
291 Axes(x, y) =>
292 {
293 write!(writer, " axes {}{}",
294 match x
295 {
296 XAxis::X1 => "x1",
297 XAxis::X2 => "x2",
298 },
299 match y
300 {
301 YAxis::Y1 => "y1",
302 YAxis::Y2 => "y2",
303 }
304 );
305 }
306 }
307 }
308
309 fn write_data(&self, writer: &mut dyn Writer)
310 {
311 for d in &self.data
312 {
313 writer.write_le_f64(*d);
314 }
315 }
316}
317
318pub struct LabelData
319{
320 pub label_type: LabelType,
321 pub text: String,
322 pub options: Vec<LabelOption<String>>,
323}
324
325impl LabelData
326{
327 fn new(label_type: LabelType) -> Self
328 {
329 Self {
330 label_type,
331 text: "".into(),
332 options: vec![],
333 }
334 }
335
336 pub fn set(&mut self, text: String, options: Vec<LabelOption<String>>)
337 {
338 self.text = text;
339 self.options = options;
340 }
341
342 pub fn write_out_commands(&self, writer: &mut dyn Writer)
343 {
344 let w = writer;
345 w.write_str("set ");
346
347 self.label_type.write_label_str(w);
348
349 w.write_str(" \"");
350 w.write_str(&escape(&self.text));
351 w.write_str("\"");
352
353 write_out_label_options(self.label_type, &self.options[..], w);
354
355 w.write_str("\n");
356 }
357
358 pub fn reset_state(&self, writer: &mut dyn Writer)
359 {
360 if let Label(tag, ..) = self.label_type
361 {
362 writeln!(writer, "unset label {}", tag);
363 }
364 }
365}
366
367#[derive(Copy, Clone)]
368pub enum LabelType
369{
370 XLabel,
371 YLabel,
372 X2Label,
373 Y2Label,
374 ZLabel,
375 CBLabel,
376 TitleLabel,
377 Label(i32, Coordinate, Coordinate),
378 AxesTicks,
379}
380
381impl LabelType
382{
383 fn is_label(&self) -> bool
384 {
385 matches!(*self, Label(..))
386 }
387
388 fn write_label_str(&self, w: &mut dyn Writer)
389 {
390 match *self
391 {
392 XLabel =>
393 {
394 w.write_str("xlabel");
395 }
396 YLabel =>
397 {
398 w.write_str("ylabel");
399 }
400 X2Label =>
401 {
402 w.write_str("x2label");
403 }
404 Y2Label =>
405 {
406 w.write_str("y2label");
407 }
408 ZLabel =>
409 {
410 w.write_str("zlabel");
411 }
412 CBLabel =>
413 {
414 w.write_str("cblabel");
415 }
416 TitleLabel =>
417 {
418 w.write_str("title");
419 }
420 Label(tag, ..) =>
421 {
422 write!(w, "label {}", tag);
423 }
424 _ => panic!("Invalid label type"),
425 }
426 }
427
428 fn from_axis(axis_type: TickAxis) -> Self
429 {
430 match axis_type
431 {
432 TickAxis::X => XLabel,
433 TickAxis::Y => YLabel,
434 TickAxis::X2 => X2Label,
435 TickAxis::Y2 => Y2Label,
436 TickAxis::Z => ZLabel,
437 TickAxis::CB => CBLabel,
438 }
439 }
440}
441
442pub fn write_out_label_options(
443 label_type: LabelType, options: &[LabelOption<String>], writer: &mut dyn Writer,
444)
445{
446 let w = writer;
447 if let Label(_, x, y) = label_type
448 {
449 write!(w, " at {},{} front", x, y);
450 }
451
452 first_opt! {options,
453 TextOffset(x, y) =>
454 {
455 write!(w, " offset character {:.12e},{:.12e}", x, y);
456 }
457 }
458
459 first_opt! {options,
460 TextColor(ref s) =>
461 {
462 write!(w, r#" tc {}"#, s.command());
463 }
464 }
465
466 first_opt! {options,
467 Font(ref f, s) =>
468 {
469 write!(w, r#" font "{},{}""#, f, s);
470 }
471 }
472
473 first_opt! {options,
474 Rotate(a) =>
475 {
476 write!(w, " rotate by {:.12e}", a);
477 }
478 }
479
480 if label_type.is_label()
481 {
482 let mut have_point = false;
483 first_opt! {options,
484 MarkerSymbol(s) =>
485 {
486 write!(w, " point pt {}", char_to_symbol(s));
487 have_point = true;
488 }
489 }
490
491 if have_point
492 {
493 first_opt! {options,
494 MarkerColor(ref s) =>
495 {
496 write!(w, r#" lc {}"#, s.command());
497 }
498 }
499
500 first_opt! {options,
501 MarkerSize(z) =>
502 {
503 write!(w, " ps {:.12e}", z);
504 }
505 }
506 }
507
508 first_opt! {options,
509 TextAlign(a) =>
510 {
511 write!(w, "{}", match a
512 {
513 AlignLeft => " left",
514 AlignRight => " right",
515 _ => " center",
516 });
517 }
518 }
519 }
520}
521
522#[derive(Copy, Clone, PartialEq)]
523pub enum TickAxis
524{
525 X,
526 Y,
527 X2,
528 Y2,
529 Z,
530 CB,
531}
532
533impl TickAxis
534{
535 pub fn get_axis_str(&self) -> &str
536 {
537 match *self
538 {
539 TickAxis::X => "x",
540 TickAxis::Y => "y",
541 TickAxis::X2 => "x2",
542 TickAxis::Y2 => "y2",
543 TickAxis::Z => "z",
544 TickAxis::CB => "cb",
545 }
546 }
547
548 pub fn get_tick_str(&self) -> &str
549 {
550 match *self
551 {
552 TickAxis::X => "xtics",
553 TickAxis::Y => "ytics",
554 TickAxis::X2 => "x2tics",
555 TickAxis::Y2 => "y2tics",
556 TickAxis::Z => "ztics",
557 TickAxis::CB => "cbtics",
558 }
559 }
560
561 pub fn get_mtick_str(&self) -> &str
562 {
563 match *self
564 {
565 TickAxis::X => "mxtics",
566 TickAxis::Y => "mytics",
567 TickAxis::X2 => "mx2tics",
568 TickAxis::Y2 => "my2tics",
569 TickAxis::Z => "mztics",
570 TickAxis::CB => "mcbtics",
571 }
572 }
573
574 pub fn get_range_str(&self) -> &str
575 {
576 match *self
577 {
578 TickAxis::X => "xrange",
579 TickAxis::Y => "yrange",
580 TickAxis::X2 => "x2range",
581 TickAxis::Y2 => "y2range",
582 TickAxis::Z => "zrange",
583 TickAxis::CB => "cbrange",
584 }
585 }
586}
587
588pub enum PlotType
589{
590 Lines,
591 Points,
592 LinesPoints,
593 XErrorLines,
594 YErrorLines,
595 XErrorBars,
596 XYErrorBars,
597 YErrorBars,
598 FillBetween,
599 Polygons,
600 Boxes,
601 BoxErrorBars,
602 BoxAndWhisker,
603 BoxXYError,
604 Pm3D,
605 Image,
606}
607
608impl PlotType
609{
610 fn is_line(&self) -> bool
611 {
612 matches!(
613 *self,
614 Lines
615 | LinesPoints
616 | XErrorLines
617 | Boxes | YErrorLines
618 | BoxAndWhisker
619 | BoxXYError | BoxErrorBars
620 | Polygons
621 )
622 }
623
624 fn is_points(&self) -> bool
625 {
626 matches!(
627 *self,
628 Points
629 | LinesPoints
630 | XErrorLines
631 | YErrorLines
632 | XErrorBars | YErrorBars
633 | XYErrorBars
634 )
635 }
636
637 fn is_fill(&self) -> bool
638 {
639 matches!(
640 *self,
641 Boxes | FillBetween | BoxAndWhisker | BoxXYError | BoxErrorBars | Polygons
642 )
643 }
644}
645
646pub enum TickType
647{
648 None,
649 Custom(Vec<Tick<f64, String>>),
650 Auto(AutoOption<f64>, u32),
651}
652
653pub struct AxisData
654{
655 pub tick_options: Vec<TickOption<String>>,
656 pub label_options: Vec<LabelOption<String>>,
657 pub tick_type: TickType,
658 pub log_base: Option<f64>,
659 pub axis: TickAxis,
660 pub min: AutoOption<f64>,
661 pub max: AutoOption<f64>,
662 pub reverse: bool,
663 pub grid: bool,
664 pub mgrid: bool,
665 pub is_time: bool,
666 pub show: bool,
667 pub label: LabelData,
668 pub options: Vec<PlotOption<String>>,
669}
670
671impl AxisData
672{
673 pub fn new(axis: TickAxis) -> Self
674 {
675 AxisData {
676 tick_options: vec![],
677 label_options: vec![],
678 tick_type: TickType::Auto(Auto, 0),
679 log_base: None,
680 axis,
681 min: Auto,
682 max: Auto,
683 reverse: false,
684 grid: false,
685 mgrid: false,
686 is_time: false,
687 show: false,
688 label: LabelData::new(LabelType::from_axis(axis)),
689 options: vec![],
690 }
691 }
692
693 pub fn write_out_commands(&self, w: &mut dyn Writer, version: GnuplotVersion)
694 {
695 if self.axis != TickAxis::CB
696 {
697 if self.show
698 {
699 w.write_str("set ");
700 w.write_str(self.axis.get_axis_str());
701 w.write_str("zeroaxis ");
702
703 AxesCommonData::write_color_options(
704 w,
705 &self.options,
706 false,
707 Some(ColorType::RGBString("black".into())),
708 );
709 AxesCommonData::write_line_options(w, &self.options, version);
710 }
711 else
712 {
713 w.write_str("unset ");
714 w.write_str(self.axis.get_axis_str());
715 w.write_str("zeroaxis ");
716 }
717 }
718
719 w.write_str("\n");
720
721 let log = match self.log_base
722 {
723 Some(base) =>
724 {
725 w.write_str("set logscale ");
726 w.write_str(self.axis.get_axis_str());
727 write!(w, " {:.12e}", base);
728 true
729 }
730 None =>
731 {
732 w.write_str("unset logscale ");
733 w.write_str(self.axis.get_axis_str());
734 false
735 }
736 };
737 w.write_str("\n");
738
739 w.write_str("set ");
740 w.write_str(self.axis.get_axis_str());
741 w.write_str("data");
742 if self.is_time
743 {
744 w.write_str(" time");
745 }
746 w.write_str("\n");
747
748 match self.tick_type
749 {
750 TickType::Auto(_, mticks) =>
751 {
752 write!(w, "set m{} ", self.axis.get_tick_str());
753 if log
754 {
755 writeln!(w, "default");
756 }
757 else
758 {
759 writeln!(w, "{}", mticks as i32 + 1);
760 }
761 }
762 _ =>
763 {
764 writeln!(w, "unset m{}", self.axis.get_tick_str());
765 }
766 }
767 w.write_str("\n");
768
769 w.write_str("set ");
770 w.write_str(self.axis.get_range_str());
771 w.write_str(" [");
772 match self.min
773 {
774 Fix(v) => write!(w, "{:.12e}", v),
775 Auto => w.write_str("*"),
776 };
777 w.write_str(":");
778 match self.max
779 {
780 Fix(v) => write!(w, "{:.12e}", v),
781 Auto => w.write_str("*"),
782 };
783 if self.reverse
784 {
785 w.write_str("] reverse\n");
786 }
787 else
788 {
789 w.write_str("]\n");
790 }
791
792 let mut write_tick_options = true;
793 match self.tick_type
794 {
795 TickType::None =>
796 {
797 write!(w, "unset {0}", self.axis.get_tick_str());
798 write_tick_options = false;
799 }
800 TickType::Auto(incr, _) =>
801 {
802 w.write_str("set ");
803 w.write_str(self.axis.get_tick_str());
804
805 match incr
806 {
807 Auto =>
808 {
809 w.write_str(" autofreq");
810 }
811 Fix(incr) =>
812 {
813 if incr <= 0.0
814 {
815 panic!("'incr' must be positive, but is actually {}", incr);
816 }
817 w.write_str(" ");
818 write!(w, " {:.12e}", incr);
819 }
820 }
821 }
822 TickType::Custom(ref ticks) =>
823 {
824 w.write_str("set ");
825 w.write_str(self.axis.get_tick_str());
826 w.write_str(" (");
827
828 let mut first = true;
829 for tick in ticks
830 {
831 if first
832 {
833 first = false;
834 }
835 else
836 {
837 w.write_str(",");
838 }
839
840 let a = Auto;
841 let (ref pos, label, level) = match *tick
842 {
843 Minor(ref pos) => (pos, &a, 1),
844 Major(ref pos, ref label) => (pos, label, 0),
845 };
846
847 match *label
848 {
849 Fix(ref label) =>
850 {
851 w.write_str("\"");
852 w.write_str(&label[..]);
853 w.write_str("\" ");
854 }
855 Auto => (),
856 }
857 write!(w, "{:.12e} {}", pos.get(), level);
858 }
859 w.write_str(")");
860 }
861 }
862
863 if write_tick_options
864 {
865 let label_options = &self.label_options;
866 let tick_options = &self.tick_options;
867
868 write_out_label_options(AxesTicks, &label_options[..], &mut *w);
869
870 first_opt! {tick_options,
871 OnAxis(b) =>
872 {
873 w.write_str(match b
874 {
875 true => " axis",
876 false => " border",
877 });
878 }
879 }
880
881 first_opt! {tick_options,
882 Mirror(b) =>
883 {
884 w.write_str(match b
885 {
886 true => " mirror",
887 false => " nomirror",
888 });
889 }
890 }
891
892 first_opt! {tick_options,
893 Inward(b) =>
894 {
895 w.write_str(match b
896 {
897 true => " in",
898 false => " out",
899 });
900 }
901 }
902
903 let mut minor_scale = 0.5;
904 let mut major_scale = 0.5;
905
906 first_opt! {tick_options,
907 MinorScale(s) =>
908 {
909 minor_scale = s;
910 }
911 }
912
913 first_opt! {tick_options,
914 MajorScale(s) =>
915 {
916 major_scale = s;
917 }
918 }
919
920 write!(w, " scale {:.12e},{:.12e}", major_scale, minor_scale);
921
922 first_opt! {tick_options,
923 Format(ref f) =>
924 {
925 write!(w, r#" format "{}""#, f);
926 }
927 }
928 }
929 w.write_str("\n");
930 self.label.write_out_commands(w);
931 w.write_str("\n");
932 }
933
934 pub fn set_ticks_custom<T: DataType, TL: IntoIterator<Item = Tick<T, String>>>(
935 &mut self, ticks: TL, tick_options: Vec<TickOption<String>>,
936 label_options: Vec<LabelOption<String>>,
937 )
938 {
939 self.tick_type = TickType::Custom(
940 ticks
941 .into_iter()
942 .map(|t| match t
943 {
944 Major(t, l) => Major(t.get(), l),
945 Minor(t) => Minor(t.get()),
946 })
947 .collect(),
948 );
949 self.tick_options = tick_options;
950 self.label_options = label_options;
951 }
952
953 pub fn set_ticks(
954 &mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
955 tick_options: Vec<TickOption<String>>, label_options: Vec<LabelOption<String>>,
956 )
957 {
958 if let Some((incr, mticks)) = tick_placement
959 {
960 self.tick_type = TickType::Auto(incr, mticks);
961 self.tick_options = tick_options;
962 self.label_options = label_options;
963 }
964 else
965 {
966 self.tick_type = TickType::None
967 }
968 }
969
970 pub fn set_range(&mut self, min: AutoOption<f64>, max: AutoOption<f64>)
971 {
972 self.min = min;
973 self.max = max;
974 }
975
976 pub fn set_log(&mut self, base: Option<f64>)
977 {
978 self.log_base = base;
979 }
980
981 pub fn set_reverse(&mut self, reverse: bool)
982 {
983 self.reverse = reverse;
984 }
985
986 pub fn set_grid(&mut self, show: bool)
987 {
988 self.grid = show;
989 }
990
991 pub fn set_minor_grid(&mut self, show: bool)
992 {
993 self.mgrid = show;
994 }
995
996 pub fn set_time(&mut self, is_time: bool)
997 {
998 self.is_time = is_time;
999 }
1000}
1001
1002pub fn char_to_symbol(c: char) -> i32
1003{
1004 match c
1005 {
1006 '.' => 0,
1007 '+' => 1,
1008 'x' => 2,
1009 '*' => 3,
1010 's' => 4,
1011 'S' => 5,
1012 'o' => 6,
1013 'O' => 7,
1014 't' => 8,
1015 'T' => 9,
1016 'd' => 10,
1017 'D' => 11,
1018 'r' => 12,
1019 'R' => 13,
1020 a => panic!("Invalid symbol {}", a),
1021 }
1022}
1023
1024enum DataSourceType
1025{
1026 Record,
1027 Array,
1028 SizedArray(f64, f64, f64, f64),
1029}
1030
1031pub struct Margins
1032{
1033 pub left: Option<f32>,
1034 pub right: Option<f32>,
1035 pub top: Option<f32>,
1036 pub bottom: Option<f32>,
1037}
1038
1039impl Default for Margins
1040{
1041 fn default() -> Self
1042 {
1043 Self::new()
1044 }
1045}
1046
1047impl Margins
1048{
1049 pub fn new() -> Self
1050 {
1051 Margins {
1052 left: None,
1053 right: None,
1054 top: None,
1055 bottom: None,
1056 }
1057 }
1058
1059 pub fn write_out_commands(&self, w: &mut dyn Writer)
1060 {
1061 let mut write_margin = |margin, v| {
1062 write!(w, "set {}", margin);
1063 if let Some(v) = v
1064 {
1065 write!(w, " at screen {}", v);
1066 }
1067 w.write_str("\n");
1068 };
1069
1070 write_margin("lmargin", self.left);
1071 write_margin("rmargin", self.right);
1072 write_margin("tmargin", self.top);
1073 write_margin("bmargin", self.bottom);
1074 }
1075}
1076
1077#[derive(Copy, Clone)]
1078pub struct Position
1079{
1080 x: f64,
1081 y: f64,
1082}
1083
1084#[derive(Copy, Clone)]
1085pub struct Size
1086{
1087 w: f64,
1088 h: f64,
1089}
1090
1091pub struct AxesCommonData
1092{
1093 pub grid_options: Vec<PlotOption<String>>,
1094 pub minor_grid_options: Vec<PlotOption<String>>,
1095 pub grid_front: bool,
1096 pub elems: Vec<PlotElement>,
1097 pub x_axis: AxisData,
1098 pub x2_axis: AxisData,
1099 pub y_axis: AxisData,
1100 pub y2_axis: AxisData,
1101 pub cb_axis: AxisData,
1102 pub labels: Vec<LabelData>,
1103 pub title: LabelData,
1104 pub position: Option<Position>,
1105 pub size: Option<Size>,
1106 pub aspect_ratio: AutoOption<f64>,
1107 pub margins: Margins,
1108 pub palette: PaletteType<Vec<(f32, f32, f32, f32)>>,
1109 pub colormaps: Vec<(String, PaletteType<Vec<(f32, f32, f32, f32)>>)>,
1110 pub box_width: Option<(f64, bool)>,
1111}
1112
1113impl AxesCommonData
1114{
1115 pub fn new() -> AxesCommonData
1116 {
1117 let mut ret = AxesCommonData {
1118 grid_options: vec![],
1119 minor_grid_options: vec![],
1120 grid_front: false,
1121 elems: Vec::new(),
1122 x_axis: AxisData::new(TickAxis::X),
1123 y_axis: AxisData::new(TickAxis::Y),
1124 x2_axis: AxisData::new(TickAxis::X2),
1125 y2_axis: AxisData::new(TickAxis::Y2),
1126 cb_axis: AxisData::new(TickAxis::CB),
1127 labels: vec![],
1128 title: LabelData::new(TitleLabel),
1129 position: None,
1130 size: None,
1131 aspect_ratio: Auto,
1132 margins: Margins::new(),
1133 palette: COLOR.to_one_way_owned(),
1134 colormaps: Vec::new(),
1135 box_width: None,
1136 };
1137 ret.x2_axis.tick_type = TickType::None;
1138 ret.y2_axis.tick_type = TickType::None;
1139 ret
1140 }
1141
1142 pub fn write_grid_options(&self, c: &mut dyn Writer, axes: &[TickAxis], version: GnuplotVersion)
1143 {
1144 if !axes.is_empty()
1145 {
1146 c.write_str("set grid ");
1147 for axis in axes
1148 {
1149 c.write_str(axis.get_tick_str());
1150 c.write_str(" ");
1151 if self.x_axis.axis == *axis && self.x_axis.mgrid
1152 || self.y_axis.axis == *axis && self.y_axis.mgrid
1153 || self.x2_axis.axis == *axis && self.x2_axis.mgrid
1154 || self.y2_axis.axis == *axis && self.y2_axis.mgrid
1155 {
1156 c.write_str(axis.get_mtick_str());
1157 c.write_str(" ");
1158 }
1159 }
1160
1161 if self.grid_front
1162 {
1163 c.write_str("front ");
1164 }
1165 else
1166 {
1167 c.write_str("back ");
1168 }
1169
1170 AxesCommonData::write_line_options(c, &self.grid_options, version);
1171 AxesCommonData::write_color_options(c, &self.grid_options, false, None);
1172 c.write_str(", ");
1173 AxesCommonData::write_line_options(c, &self.minor_grid_options, version);
1174 AxesCommonData::write_color_options(c, &self.minor_grid_options, false, None);
1175 c.write_str("\n");
1176 }
1177 }
1178
1179 pub fn write_line_options(
1180 c: &mut dyn Writer, options: &[PlotOption<String>], version: GnuplotVersion,
1181 )
1182 {
1183 let mut found = false;
1184 c.write_str(" lw ");
1185 first_opt! {options,
1186 LineWidth(w) =>
1187 {
1188 write!(c, "{:.12e}", w);
1189 found = true;
1190 }
1191 }
1192 if !found
1193 {
1194 c.write_str("1");
1195 }
1196
1197 if version.major >= 5
1198 {
1199 first_opt! {options,
1200 LineStyle(d) =>
1201 {
1202 write!(c, " dt {}", d.to_int());
1203 }
1204 }
1205 }
1206 else
1207 {
1208 first_opt! {options,
1209 LineStyle(d) =>
1210 {
1211 write!(c, " lt {}", d.to_int());
1212 }
1213 }
1214 }
1215 }
1216
1217 pub fn write_color_options(
1218 c: &mut dyn Writer, options: &[PlotOption<String>], is_fill: bool,
1219 default: Option<ColorType>,
1220 )
1221 {
1222 let main_type = if is_fill { "fillcolor" } else { "linecolor" };
1223
1224 let mut col = default.as_ref();
1225 first_opt! {options,
1226 Color(ref s) =>
1227 {
1228 col = Some(s)
1229 }
1230 }
1231 if let Some(s) = col
1232 {
1233 write!(c, " {main_type} {}", s.command());
1234 }
1235 }
1236
1237 pub fn write_out_commands(
1238 &self, writer: &mut dyn Writer, auto_layout: bool, version: GnuplotVersion,
1239 )
1240 {
1241 let w = writer;
1242 if let Some(pos) = self.position
1243 {
1244 writeln!(w, "set origin {:.12e},{:.12e}", pos.x, pos.y);
1245 }
1246 else if !auto_layout
1247 {
1248 writeln!(w, "set origin");
1249 }
1250 if let Some(size) = self.size
1251 {
1252 writeln!(w, "set size {:.12e},{:.12e}", size.w, size.h);
1253 }
1254 else if !auto_layout
1255 {
1256 writeln!(w, "set size");
1257 }
1258
1259 match self.aspect_ratio
1260 {
1261 Fix(r) =>
1262 {
1263 writeln!(w, "set size ratio {:.12e}", r);
1264 }
1265 Auto =>
1266 {
1267 writeln!(w, "set size noratio");
1268 }
1269 }
1270 self.margins.write_out_commands(w);
1271
1272 if !self.colormaps.is_empty()
1273 {
1274 for (name, map) in &self.colormaps
1275 {
1276 map.write_out_commands(w);
1277 writeln!(w, "set colormap new {name}");
1278 }
1279 }
1280 self.palette.write_out_commands(w);
1281
1282 if let Some((width, is_relative)) = self.box_width
1283 {
1284 let scale = if is_relative { "relative" } else { "absolute" };
1285 writeln!(w, "set boxwidth {width} {scale}");
1286 }
1287
1288 self.x_axis.write_out_commands(w, version);
1289 self.y_axis.write_out_commands(w, version);
1290 self.x2_axis.write_out_commands(w, version);
1291 self.y2_axis.write_out_commands(w, version);
1292 self.cb_axis.write_out_commands(w, version);
1293 self.title.write_out_commands(w);
1294 for label in &self.labels
1295 {
1296 label.write_out_commands(w);
1297 }
1298 }
1299
1300 pub fn write_out_elements(
1301 &self, cmd: &str, data_directory: Option<&str>, writer: &mut dyn Writer,
1302 version: GnuplotVersion,
1303 )
1304 {
1305 if let Some(data_directory) = data_directory
1306 {
1307 for (i, e) in self.elems.iter().enumerate()
1308 {
1309 let filename = path::Path::new(data_directory).join(format!("{i}.bin"));
1310 let mut file = fs::File::create(&filename).unwrap();
1311 e.write_data(&mut file);
1312 }
1313 }
1314
1315 write!(writer, "{}", cmd);
1316
1317 let mut first = true;
1318 for (i, e) in self.elems.iter().enumerate()
1319 {
1320 if e.num_rows == 0
1321 {
1322 continue;
1323 }
1324 if !first
1325 {
1326 write!(writer, ",");
1327 }
1328 let source = if let Some(data_directory) = data_directory
1329 {
1330 escape(
1331 path::Path::new(data_directory)
1332 .join(format!("{i}.bin"))
1333 .to_str()
1334 .unwrap(),
1335 )
1336 }
1337 else
1338 {
1339 "-".into()
1340 };
1341 e.write_args(&source, writer, version);
1342 first = false;
1343 }
1344
1345 writeln!(writer);
1346
1347 if data_directory.is_none()
1348 {
1349 for e in self.elems.iter()
1350 {
1351 e.write_data(writer);
1352 }
1353 }
1354 }
1355
1356 pub fn reset_state(&self, writer: &mut dyn Writer)
1357 {
1358 for label in &self.labels
1359 {
1360 label.reset_state(writer);
1361 }
1362 }
1363}
1364
1365#[doc(hidden)]
1366pub trait AxesCommonPrivate
1367{
1368 fn get_common_data(&self) -> &AxesCommonData;
1369 fn get_common_data_mut(&mut self) -> &mut AxesCommonData;
1370}
1371
1372pub trait AxesCommon: AxesCommonPrivate
1373{
1374 /// Set the position of the axes on the figure using grid coordinates.
1375 /// # Arguments
1376 /// * `nrow` - Number of rows in the grid. Must be greater than 0.
1377 /// * `ncol` - Number of columns in the grid. Must be greater than 0.
1378 /// * `pos` - Which grid cell to place this axes in, counting from top-left corner,
1379 /// going left and then down, starting at 0.
1380 fn set_pos_grid(&mut self, nrow: u32, ncol: u32, pos: u32) -> &mut Self
1381 {
1382 assert!(nrow > 0);
1383 assert!(ncol > 0);
1384 assert!(pos < nrow * ncol);
1385 let width = 1.0 / (ncol as f64);
1386 let height = 1.0 / (nrow as f64);
1387 let x = (pos % ncol) as f64 * width;
1388 let y = 1.0 - (1.0 + (pos / ncol) as f64) * height;
1389
1390 self.get_common_data_mut().position = Some(Position { x, y });
1391 self.get_common_data_mut().size = Some(Size {
1392 w: width,
1393 h: height,
1394 });
1395 self
1396 }
1397
1398 /// Set the position of the axes on the figure using screen coordinates.
1399 /// The coordinates refer to the bottom-left corner of the axes
1400 /// # Arguments
1401 /// * `x` - X position. Ranges from 0 to 1
1402 /// * `y` - Y position. Ranges from 0 to 1
1403 fn set_pos(&mut self, x: f64, y: f64) -> &mut Self
1404 {
1405 self.get_common_data_mut().position = Some(Position { x, y });
1406 self
1407 }
1408
1409 /// Set the size of the axes
1410 /// # Arguments
1411 /// * `w` - Width. Ranges from 0 to 1
1412 /// * `h` - Height. Ranges from 0 to 1
1413 fn set_size(&mut self, w: f64, h: f64) -> &mut Self
1414 {
1415 self.get_common_data_mut().size = Some(Size { w, h });
1416 self
1417 }
1418
1419 /// Set the width of boxes in any box plots on the axes (for example [boxes()](crate::Axes2D::boxes),
1420 /// [box_and_whisker()](crate::Axes2D::box_and_whisker))
1421 /// # Arguments
1422 /// * `width` - Width of boxes.
1423 /// * `is_relative` - if `true`, `width` is interpreted as a fraction of the default box width.
1424 /// if `false` width is an absolute value in the units of the x axis
1425 fn set_box_width(&mut self, width: f64, is_relative: bool) -> &mut Self
1426 {
1427 self.get_common_data_mut().box_width = Some((width, is_relative));
1428 self
1429 }
1430
1431 /// Set the aspect ratio of the axes
1432 /// # Arguments
1433 /// * `ratio` - The aspect ratio. Set to Auto to return the ratio to default
1434 fn set_aspect_ratio(&mut self, ratio: AutoOption<f64>) -> &mut Self
1435 {
1436 self.get_common_data_mut().aspect_ratio = ratio;
1437 self
1438 }
1439
1440 /// Set the label for the X axis
1441 /// # Arguments
1442 /// * `text` - Text of the label. Pass an empty string to hide the label
1443 /// * `options` - Array of LabelOption controlling the appearance of the label. Relevant options are:
1444 /// * `Offset` - Specifies the offset of the label
1445 /// * `Font` - Specifies the font of the label
1446 /// * `TextColor` - Specifies the color of the label
1447 /// * `Rotate` - Specifies the rotation of the label
1448 /// * `Align` - Specifies how to align the label
1449 fn set_x_label<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>]) -> &'l mut Self
1450 {
1451 self.get_common_data_mut()
1452 .x_axis
1453 .label
1454 .set(text.into(), options.to_one_way_owned());
1455 self
1456 }
1457
1458 /// Like `set_x_label`, but for the Y axis
1459 fn set_y_label<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>]) -> &'l mut Self
1460 {
1461 self.get_common_data_mut()
1462 .y_axis
1463 .label
1464 .set(text.into(), options.to_one_way_owned());
1465 self
1466 }
1467
1468 /// Like `set_x_label`, but for the secondary X axis
1469 fn set_x2_label<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>]) -> &'l mut Self
1470 {
1471 self.get_common_data_mut()
1472 .x2_axis
1473 .label
1474 .set(text.into(), options.to_one_way_owned());
1475 self
1476 }
1477
1478 /// Like `set_x_label`, but for the secondary Y axis
1479 fn set_y2_label<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>]) -> &'l mut Self
1480 {
1481 self.get_common_data_mut()
1482 .y2_axis
1483 .label
1484 .set(text.into(), options.to_one_way_owned());
1485 self
1486 }
1487
1488 /// Like `set_x_label`, but for the color bar
1489 fn set_cb_label<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>]) -> &'l mut Self
1490 {
1491 self.get_common_data_mut()
1492 .cb_axis
1493 .label
1494 .set(text.into(), options.to_one_way_owned());
1495 self
1496 }
1497
1498 /// Set the title for the axes
1499 /// # Arguments
1500 /// * `text` - Text of the title. Pass an empty string to hide the title
1501 /// * `options` - Array of LabelOption<&str> controlling the appearance of the title. Relevant options are:
1502 /// * `Offset` - Specifies the offset of the label
1503 /// * `Font` - Specifies the font of the label
1504 /// * `TextColor` - Specifies the color of the label
1505 /// * `Rotate` - Specifies the rotation of the label
1506 /// * `Align` - Specifies how to align the label
1507 fn set_title<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>]) -> &'l mut Self
1508 {
1509 self.get_common_data_mut()
1510 .title
1511 .set(text.into(), options.to_one_way_owned());
1512 self
1513 }
1514
1515 /// Adds a label to the plot, with an optional marker.
1516 /// # Arguments
1517 /// * `text` - Text of the label
1518 /// * `x` - X coordinate of the label
1519 /// * `y` - Y coordinate of the label
1520 /// * `options` - Array of LabelOption<&str> controlling the appearance of the label. Relevant options are:
1521 /// * `Offset` - Specifies the offset of the label
1522 /// * `Font` - Specifies the font of the label
1523 /// * `TextColor` - Specifies the color of the label
1524 /// * `Rotate` - Specifies the rotation of the label
1525 /// * `Align` - Specifies how to align the label
1526 /// * `MarkerSymbol` - Specifies the symbol for the marker. Omit to hide the marker
1527 /// * `MarkerSize` - Specifies the size for the marker
1528 /// * `MarkerColor` - Specifies the color for the marker
1529 fn label<'l>(
1530 &'l mut self, text: &str, x: Coordinate, y: Coordinate, options: &[LabelOption<&str>],
1531 ) -> &'l mut Self
1532 {
1533 {
1534 let labels = &mut self.get_common_data_mut().labels;
1535 let mut label = LabelData::new(Label(labels.len() as i32 + 1, x, y));
1536 label.set(text.into(), options.to_one_way_owned());
1537 labels.push(label);
1538 }
1539 self
1540 }
1541
1542 /// Sets the properties of the ticks on the X axis.
1543 ///
1544 /// # Arguments
1545 /// * `tick_placement` - Controls the placement of the ticks. Pass `None` to hide the ticks. Otherwise, the first tuple value controls the spacing
1546 /// of the major ticks (in axes units), otherwise set it to `Auto` to let gnuplot decide the spacing automatically. The second
1547 /// tuple value specifies the number of minor ticks. For logarithmic axes, non-zero values mean that the number of ticks usually
1548 /// equals to `ceil(log_base) - 2`.
1549 /// * `tick_options` - Array of TickOption controlling the appearance of the ticks
1550 /// * `label_options` - Array of LabelOption<&str> controlling the appearance of the tick labels. Relevant options are:
1551 /// * `Offset` - Specifies the offset of the label
1552 /// * `Font` - Specifies the font of the label
1553 /// * `TextColor` - Specifies the color of the label
1554 /// * `Rotate` - Specifies the rotation of the label
1555 /// * `Align` - Specifies how to align the label
1556 fn set_x_ticks<'l>(
1557 &'l mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
1558 tick_options: &[TickOption<&str>], label_options: &[LabelOption<&str>],
1559 ) -> &'l mut Self
1560 {
1561 self.get_common_data_mut().x_axis.set_ticks(
1562 tick_placement,
1563 tick_options.to_one_way_owned(),
1564 label_options.to_one_way_owned(),
1565 );
1566 self
1567 }
1568
1569 /// Like `set_x_ticks` but for the Y axis.
1570 fn set_y_ticks<'l>(
1571 &'l mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
1572 tick_options: &[TickOption<&str>], label_options: &[LabelOption<&str>],
1573 ) -> &'l mut Self
1574 {
1575 self.get_common_data_mut().y_axis.set_ticks(
1576 tick_placement,
1577 tick_options.to_one_way_owned(),
1578 label_options.to_one_way_owned(),
1579 );
1580 self
1581 }
1582
1583 /// Like `set_x_ticks` but for the secondary X axis.
1584 ///
1585 /// Note that by default, these are hidden.
1586 fn set_x2_ticks<'l>(
1587 &'l mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
1588 tick_options: &[TickOption<&str>], label_options: &[LabelOption<&str>],
1589 ) -> &'l mut Self
1590 {
1591 self.get_common_data_mut().y2_axis.set_ticks(
1592 tick_placement,
1593 tick_options.to_one_way_owned(),
1594 label_options.to_one_way_owned(),
1595 );
1596 self
1597 }
1598
1599 /// Like `set_x_ticks` but for the secondary Y axis.
1600 ///
1601 /// Note that by default, these are hidden.
1602 fn set_y2_ticks<'l>(
1603 &'l mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
1604 tick_options: &[TickOption<&str>], label_options: &[LabelOption<&str>],
1605 ) -> &'l mut Self
1606 {
1607 self.get_common_data_mut().y2_axis.set_ticks(
1608 tick_placement,
1609 tick_options.to_one_way_owned(),
1610 label_options.to_one_way_owned(),
1611 );
1612 self
1613 }
1614
1615 /// Like `set_x_ticks` but for the color bar axis.
1616 fn set_cb_ticks<'l>(
1617 &'l mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
1618 tick_options: &[TickOption<&str>], label_options: &[LabelOption<&str>],
1619 ) -> &'l mut Self
1620 {
1621 self.get_common_data_mut().cb_axis.set_ticks(
1622 tick_placement,
1623 tick_options.to_one_way_owned(),
1624 label_options.to_one_way_owned(),
1625 );
1626 self
1627 }
1628
1629 /// Sets ticks on the X axis with specified labels at specified positions.
1630 ///
1631 /// # Arguments
1632 ///
1633 /// * `ticks` - The locations and labels of the added ticks.
1634 /// The label can contain a single C printf style floating point formatting specifier which will be replaced by the
1635 /// location of the tic.
1636 /// * `tick_options` - Array of TickOption controlling the appearance of the ticks
1637 /// * `label_options` - Array of LabelOption<&str> controlling the appearance of the tick labels. Relevant options are:
1638 /// * `Offset` - Specifies the offset of the label
1639 /// * `Font` - Specifies the font of the label
1640 /// * `TextColor` - Specifies the color of the label
1641 /// * `Rotate` - Specifies the rotation of the label
1642 /// * `Align` - Specifies how to align the label
1643 fn set_x_ticks_custom<
1644 'l,
1645 T: DataType,
1646 S: ToString,
1647 TickT: Borrow<Tick<T, S>>,
1648 TL: IntoIterator<Item = TickT>,
1649 >(
1650 &'l mut self, ticks: TL, tick_options: &[TickOption<&str>],
1651 label_options: &[LabelOption<&str>],
1652 ) -> &'l mut Self
1653 {
1654 self.get_common_data_mut().x_axis.set_ticks_custom(
1655 ticks.into_iter().map(|e| e.borrow().to_one_way_owned()),
1656 tick_options.to_one_way_owned(),
1657 label_options.to_one_way_owned(),
1658 );
1659 self
1660 }
1661
1662 /// Like `set_x_ticks_custom` but for the the Y axis.
1663 fn set_y_ticks_custom<
1664 'l,
1665 T: DataType,
1666 S: ToString,
1667 TickT: Borrow<Tick<T, S>>,
1668 TL: IntoIterator<Item = TickT>,
1669 >(
1670 &'l mut self, ticks: TL, tick_options: &[TickOption<&str>],
1671 label_options: &[LabelOption<&str>],
1672 ) -> &'l mut Self
1673 {
1674 self.get_common_data_mut().y_axis.set_ticks_custom(
1675 ticks.into_iter().map(|e| e.borrow().to_one_way_owned()),
1676 tick_options.to_one_way_owned(),
1677 label_options.to_one_way_owned(),
1678 );
1679 self
1680 }
1681
1682 /// Like `set_x_ticks_custom` but for the the secondary X axis.
1683 fn set_x2_ticks_custom<
1684 'l,
1685 T: DataType,
1686 S: ToString,
1687 TickT: Borrow<Tick<T, S>>,
1688 TL: IntoIterator<Item = TickT>,
1689 >(
1690 &'l mut self, ticks: TL, tick_options: &[TickOption<&str>],
1691 label_options: &[LabelOption<&str>],
1692 ) -> &'l mut Self
1693 {
1694 self.get_common_data_mut().x2_axis.set_ticks_custom(
1695 ticks.into_iter().map(|e| e.borrow().to_one_way_owned()),
1696 tick_options.to_one_way_owned(),
1697 label_options.to_one_way_owned(),
1698 );
1699 self
1700 }
1701
1702 /// Like `set_x_ticks_custom` but for the the secondary Y axis.
1703 fn set_y2_ticks_custom<
1704 'l,
1705 T: DataType,
1706 S: ToString,
1707 TickT: Borrow<Tick<T, S>>,
1708 TL: IntoIterator<Item = TickT>,
1709 >(
1710 &'l mut self, ticks: TL, tick_options: &[TickOption<&str>],
1711 label_options: &[LabelOption<&str>],
1712 ) -> &'l mut Self
1713 {
1714 self.get_common_data_mut().y2_axis.set_ticks_custom(
1715 ticks.into_iter().map(|e| e.borrow().to_one_way_owned()),
1716 tick_options.to_one_way_owned(),
1717 label_options.to_one_way_owned(),
1718 );
1719 self
1720 }
1721
1722 /// Like `set_x_ticks_custom` but for the the color bar axis.
1723 fn set_cb_ticks_custom<
1724 'l,
1725 T: DataType,
1726 S: ToString,
1727 TickT: Borrow<Tick<T, S>>,
1728 TL: IntoIterator<Item = TickT>,
1729 >(
1730 &'l mut self, ticks: TL, tick_options: &[TickOption<&str>],
1731 label_options: &[LabelOption<&str>],
1732 ) -> &'l mut Self
1733 {
1734 self.get_common_data_mut().cb_axis.set_ticks_custom(
1735 ticks.into_iter().map(|e| e.borrow().to_one_way_owned()),
1736 tick_options.to_one_way_owned(),
1737 label_options.to_one_way_owned(),
1738 );
1739 self
1740 }
1741
1742 /// Set the range of values for the X axis.
1743 ///
1744 /// # Arguments
1745 /// * `min` - Minimum X value
1746 /// * `max` - Maximum X value
1747 fn set_x_range(&mut self, min: AutoOption<f64>, max: AutoOption<f64>) -> &mut Self
1748 {
1749 self.get_common_data_mut().x_axis.set_range(min, max);
1750 self
1751 }
1752
1753 /// Set the range of values for the Y axis.
1754 ///
1755 /// # Arguments
1756 /// * `min` - Minimum Y value
1757 /// * `max` - Maximum Y value
1758 fn set_y_range(&mut self, min: AutoOption<f64>, max: AutoOption<f64>) -> &mut Self
1759 {
1760 self.get_common_data_mut().y_axis.set_range(min, max);
1761 self
1762 }
1763
1764 /// Set the range of values for the secondary X axis.
1765 ///
1766 /// # Arguments
1767 /// * `min` - Minimum X value
1768 /// * `max` - Maximum X value
1769 fn set_x2_range(&mut self, min: AutoOption<f64>, max: AutoOption<f64>) -> &mut Self
1770 {
1771 self.get_common_data_mut().x2_axis.set_range(min, max);
1772 self
1773 }
1774
1775 /// Set the range of values for the secondary Y axis.
1776 ///
1777 /// # Arguments
1778 /// * `min` - Minimum Y value
1779 /// * `max` - Maximum Y value
1780 fn set_y2_range(&mut self, min: AutoOption<f64>, max: AutoOption<f64>) -> &mut Self
1781 {
1782 self.get_common_data_mut().y2_axis.set_range(min, max);
1783 self
1784 }
1785
1786 /// Sets X axis to reverse.
1787 /// # Arguments
1788 /// * `reverse` - Boolean, true to reverse axis, false will not reverse
1789 fn set_x_reverse(&mut self, reverse: bool) -> &mut Self
1790 {
1791 self.get_common_data_mut().x_axis.set_reverse(reverse);
1792 self
1793 }
1794
1795 /// Sets Y axis to reverse.
1796 /// # Arguments
1797 /// * `reverse` - Boolean, true to reverse axis, false will not reverse
1798 fn set_y_reverse(&mut self, reverse: bool) -> &mut Self
1799 {
1800 self.get_common_data_mut().y_axis.set_reverse(reverse);
1801 self
1802 }
1803
1804 /// Sets secondary X axis to reverse.
1805 /// # Arguments
1806 /// * `reverse` - Boolean, true to reverse axis, false will not reverse
1807 fn set_x2_reverse(&mut self, reverse: bool) -> &mut Self
1808 {
1809 self.get_common_data_mut().x2_axis.set_reverse(reverse);
1810 self
1811 }
1812
1813 /// Sets secondary Y axis to reverse.
1814 /// # Arguments
1815 /// * `reverse` - Boolean, true to reverse axis, false will not reverse
1816 fn set_y2_reverse(&mut self, reverse: bool) -> &mut Self
1817 {
1818 self.get_common_data_mut().y2_axis.set_reverse(reverse);
1819 self
1820 }
1821
1822 /// Set the range of values for the color bar axis.
1823 ///
1824 /// # Arguments
1825 /// * `min` - Minimum Y value
1826 /// * `max` - Maximum Y value
1827 fn set_cb_range(&mut self, min: AutoOption<f64>, max: AutoOption<f64>) -> &mut Self
1828 {
1829 self.get_common_data_mut().cb_axis.set_range(min, max);
1830 self
1831 }
1832
1833 /// Sets the X axis be logarithmic. Note that the range must be non-negative for this to be valid.
1834 ///
1835 /// # Arguments
1836 /// * `base` - If Some, then specifies base of the logarithm, if None makes the axis not be logarithmic
1837 fn set_x_log(&mut self, base: Option<f64>) -> &mut Self
1838 {
1839 self.get_common_data_mut().x_axis.set_log(base);
1840 self
1841 }
1842
1843 /// Sets the Y axis be logarithmic. Note that the range must be non-negative for this to be valid.
1844 ///
1845 /// # Arguments
1846 /// * `base` - If Some, then specifies base of the logarithm, if None makes the axis not be logarithmic
1847 fn set_y_log(&mut self, base: Option<f64>) -> &mut Self
1848 {
1849 self.get_common_data_mut().y_axis.set_log(base);
1850 self
1851 }
1852
1853 /// Sets the secondary X axis be logarithmic. Note that the range must be non-negative for this to be valid.
1854 ///
1855 /// # Arguments
1856 /// * `base` - If Some, then specifies base of the logarithm, if None makes the axis not be logarithmic
1857 fn set_x2_log(&mut self, base: Option<f64>) -> &mut Self
1858 {
1859 self.get_common_data_mut().x2_axis.set_log(base);
1860 self
1861 }
1862
1863 /// Sets the secondary Y axis be logarithmic. Note that the range must be non-negative for this to be valid.
1864 ///
1865 /// # Arguments
1866 /// * `base` - If Some, then specifies base of the logarithm, if None makes the axis not be logarithmic
1867 fn set_y2_log(&mut self, base: Option<f64>) -> &mut Self
1868 {
1869 self.get_common_data_mut().y2_axis.set_log(base);
1870 self
1871 }
1872
1873 /// Sets the color bar axis be logarithmic. Note that the range must be non-negative for this to be valid.
1874 ///
1875 /// # Arguments
1876 /// * `base` - If Some, then specifies base of the logarithm, if None makes the axis not be logarithmic
1877 fn set_cb_log(&mut self, base: Option<f64>) -> &mut Self
1878 {
1879 self.get_common_data_mut().cb_axis.set_log(base);
1880 self
1881 }
1882
1883 /// Shows the grid on the X axis.
1884 ///
1885 /// # Arguments
1886 /// * `show` - Whether to show the grid.
1887 fn set_x_grid(&mut self, show: bool) -> &mut Self
1888 {
1889 self.get_common_data_mut().x_axis.set_grid(show);
1890 self
1891 }
1892
1893 /// Shows the minor grid on the X axis.
1894 ///
1895 /// # Arguments
1896 /// * `show` - Whether to show the grid.
1897 fn set_x_minor_grid(&mut self, show: bool) -> &mut Self
1898 {
1899 self.get_common_data_mut().x_axis.set_minor_grid(show);
1900 self
1901 }
1902
1903 /// Shows the grid on the Y axis.
1904 ///
1905 /// # Arguments
1906 /// * `show` - Whether to show the grid.
1907 fn set_y_grid(&mut self, show: bool) -> &mut Self
1908 {
1909 self.get_common_data_mut().y_axis.set_grid(show);
1910 self
1911 }
1912
1913 /// Shows the minor grid on the Y axis.
1914 ///
1915 /// # Arguments
1916 /// * `show` - Whether to show the grid.
1917 fn set_y_minor_grid(&mut self, show: bool) -> &mut Self
1918 {
1919 self.get_common_data_mut().y_axis.set_minor_grid(show);
1920 self
1921 }
1922
1923 /// Shows the grid on the secondary X axis.
1924 ///
1925 /// # Arguments
1926 /// * `show` - Whether to show the grid.
1927 fn set_x2_grid(&mut self, show: bool) -> &mut Self
1928 {
1929 self.get_common_data_mut().x2_axis.set_grid(show);
1930 self
1931 }
1932
1933 /// Shows the minor grid on the secondary X axis.
1934 ///
1935 /// # Arguments
1936 /// * `show` - Whether to show the grid.
1937 fn set_x2_minor_grid(&mut self, show: bool) -> &mut Self
1938 {
1939 self.get_common_data_mut().x2_axis.set_minor_grid(show);
1940 self
1941 }
1942
1943 /// Shows the grid on the secondary Y axis.
1944 ///
1945 /// # Arguments
1946 /// * `show` - Whether to show the grid.
1947 fn set_y2_grid(&mut self, show: bool) -> &mut Self
1948 {
1949 self.get_common_data_mut().y2_axis.set_grid(show);
1950 self
1951 }
1952
1953 /// Shows the minor grid on the secondary Y axis.
1954 ///
1955 /// # Arguments
1956 /// * `show` - Whether to show the grid.
1957 fn set_y2_minor_grid(&mut self, show: bool) -> &mut Self
1958 {
1959 self.get_common_data_mut().y2_axis.set_minor_grid(show);
1960 self
1961 }
1962
1963 /// Shows the grid on the color bar axis.
1964 ///
1965 /// # Arguments
1966 /// * `show` - Whether to show the grid.
1967 fn set_cb_grid(&mut self, show: bool) -> &mut Self
1968 {
1969 self.get_common_data_mut().cb_axis.set_grid(show);
1970 self
1971 }
1972
1973 /// Set the grid options.
1974 ///
1975 /// # Arguments
1976 /// * `front` - Whether the grid should be in the front of the plot elements or behind them.
1977 /// * `options` - Styling options of the grid. Relevant options are:
1978 /// * `Color` - Specifies the color of the grid lines
1979 /// * `LineStyle` - Specifies the style of the grid lines
1980 /// * `LineWidth` - Specifies the width of the grid lines
1981 fn set_grid_options<'l>(&'l mut self, front: bool, options: &[PlotOption<&str>])
1982 -> &'l mut Self
1983 {
1984 self.get_common_data_mut().grid_front = front;
1985 self.get_common_data_mut().grid_options = options.to_one_way_owned();
1986 self
1987 }
1988
1989 /// Set the minor grid options.
1990 ///
1991 /// # Arguments
1992 /// * `options` - Styling options of the grid. Relevant options are:
1993 /// * `Color` - Specifies the color of the grid lines
1994 /// * `LineStyle` - Specifies the style of the grid lines
1995 /// * `LineWidth` - Specifies the width of the grid lines
1996 fn set_minor_grid_options<'l>(&'l mut self, options: &[PlotOption<&str>]) -> &'l mut Self
1997 {
1998 self.get_common_data_mut().minor_grid_options = options.to_one_way_owned();
1999 self
2000 }
2001
2002 /// Sets the X axis be time.
2003 ///
2004 /// If true, the axis is interpreted as seconds from the Unix epoch. Use the `Format` TickOption to
2005 /// specify the formatting of the ticks (see strftime format spec for valid values).
2006 ///
2007 /// # Arguments
2008 /// * `is_time` - Whether this axis is time or not.
2009 fn set_x_time(&mut self, is_time: bool) -> &mut Self
2010 {
2011 self.get_common_data_mut().x_axis.set_time(is_time);
2012 self
2013 }
2014
2015 /// Sets the Y axis be time. Note that the range must be non-negative for this to be valid.
2016 ///
2017 /// If true, the axis is interpreted as seconds from the Unix epoch. Use the `Format` TickOption to
2018 /// specify the formatting of the ticks (see strftime format spec for valid values).
2019 ///
2020 /// # Arguments
2021 /// * `is_time` - Whether this axis is time or not.
2022 fn set_y_time(&mut self, is_time: bool) -> &mut Self
2023 {
2024 self.get_common_data_mut().y_axis.set_time(is_time);
2025 self
2026 }
2027
2028 /// Sets the secondary X axis be time.
2029 ///
2030 /// If true, the axis is interpreted as seconds from the Unix epoch. Use the `Format` TickOption to
2031 /// specify the formatting of the ticks (see strftime format spec for valid values).
2032 ///
2033 /// # Arguments
2034 /// * `is_time` - Whether this axis is time or not.
2035 fn set_x2_time(&mut self, is_time: bool) -> &mut Self
2036 {
2037 self.get_common_data_mut().x2_axis.set_time(is_time);
2038 self
2039 }
2040
2041 /// Sets the secondary Y axis be time. Note that the range must be non-negative for this to be valid.
2042 ///
2043 /// If true, the axis is interpreted as seconds from the Unix epoch. Use the `Format` TickOption to
2044 /// specify the formatting of the ticks (see strftime format spec for valid values).
2045 ///
2046 /// # Arguments
2047 /// * `is_time` - Whether this axis is time or not.
2048 fn set_y2_time(&mut self, is_time: bool) -> &mut Self
2049 {
2050 self.get_common_data_mut().y2_axis.set_time(is_time);
2051 self
2052 }
2053
2054 /// Sets the color bar axis be time. Note that the range must be non-negative for this to be valid.
2055 ///
2056 /// If true, the axis is interpreted as seconds from the Unix epoch. Use the `Format` TickOption to
2057 /// specify the formatting of the ticks (see strftime format spec for valid values).
2058 ///
2059 /// # Arguments
2060 /// * `is_time` - Whether this axis is time or not.
2061 fn set_cb_time(&mut self, is_time: bool) -> &mut Self
2062 {
2063 self.get_common_data_mut().cb_axis.set_time(is_time);
2064 self
2065 }
2066
2067 /// Sets the margins of the plot.
2068 ///
2069 /// # Arguments
2070 ///
2071 /// * `margins` - The values of margins to be overriden. Specified as a fraction of the
2072 /// full drawing area, ranging from 0 to 1
2073 fn set_margins(&mut self, margins: &[MarginSide]) -> &mut Self
2074 {
2075 {
2076 let m = &mut self.get_common_data_mut().margins;
2077 *m = Margins::new();
2078 for &s in margins.iter()
2079 {
2080 match s
2081 {
2082 MarginLeft(frac) => m.left = Some(frac),
2083 MarginRight(frac) => m.right = Some(frac),
2084 MarginTop(frac) => m.top = Some(frac),
2085 MarginBottom(frac) => m.bottom = Some(frac),
2086 };
2087 }
2088 }
2089 self
2090 }
2091
2092 /// Sets the palette used for 3D surface and image plots. See the [palettes][crate::palettes]
2093 /// module for a list of predefined palettes.
2094 ///
2095 /// # Arguments
2096 /// * `palette` - What palette type to use
2097 fn set_palette(&mut self, palette: PaletteType<&[(f32, f32, f32, f32)]>) -> &mut Self
2098 {
2099 self.get_common_data_mut().palette = palette.to_one_way_owned();
2100 self
2101 }
2102
2103 /// Creates and saves a colormap in the gnuplot environment that can be used for
2104 /// later plots (see examples/color_variable.rs for example usage)
2105 ///
2106 /// # Arguments
2107 /// * `name` - The name with which to save the colormap
2108 /// * `palette` - What palette type to use
2109 fn create_colormap(
2110 &mut self, name: &str, palette: PaletteType<&[(f32, f32, f32, f32)]>,
2111 ) -> &mut Self
2112 {
2113 self.get_common_data_mut()
2114 .colormaps
2115 .push((name.to_owned(), palette.to_one_way_owned()));
2116 self
2117 }
2118}