gnuplot/
options.rs

1// Copyright (c) 2013-2014 by SiegeLord
2//
3// All rights reserved. Distributed under LGPL 3.0. For full terms see the file LICENSE.
4
5pub use self::AlignType::*;
6pub use self::ArrowheadType::*;
7pub use self::AutoOption::*;
8pub use self::BorderLocation2D::*;
9pub use self::ContourStyle::*;
10pub use self::DashType::*;
11pub use self::FillPatternType::*;
12pub use self::FillRegionType::*;
13pub use self::LabelOption::*;
14pub use self::LegendOption::*;
15pub use self::MarginSide::*;
16pub use self::PaletteType::*;
17pub use self::PlotOption::*;
18pub use self::Tick::*;
19pub use self::TickOption::*;
20pub use self::XAxis::*;
21pub use self::YAxis::*;
22use crate::util::OneWayOwned;
23use crate::writer::Writer;
24use crate::ColorType;
25
26/// An enumeration of plot options you can supply to plotting commands, governing
27/// things like line width, color and others
28#[derive(Clone, Debug, PartialOrd, PartialEq)]
29pub enum PlotOption<T>
30{
31	/// Sets the symbol used for points. The valid characters are as follows:
32	///
33	/// * `.` - dot
34	/// * `+` - plus
35	/// * `x` - cross
36	/// * `*` - star
37	/// * `s` - empty square
38	/// * `S` - filled square
39	/// * `o` - empty circle
40	/// * `O` - filled circle
41	/// * `t` - empty triangle
42	/// * `T` - filled triangle
43	/// * `d` - empty del (upside down triangle)
44	/// * `D` - filled del (upside down triangle)
45	/// * `r` - empty rhombus
46	/// * `R` - filled rhombus
47	PointSymbol(char),
48	/// Sets the size of the points. The size acts as a multiplier, with 1.0 being the default.
49	PointSize(f64),
50	/// Sets the caption of the plot element. Set to empty to hide it from the legend.
51	Caption(T),
52	/// Sets the width of lines.
53	LineWidth(f64),
54	/// Sets the color of the plot element. The passed string can be a color name
55	/// (e.g. "black" works), or an HTML color specifier (e.g. "#FFFFFF" is white). This specifies the fill color of a filled plot.
56	Color(ColorType<T>),
57	/// Sets the color of the border of a filled plot (if it has one). The passed string can be a color name
58	/// (e.g. "black" works), or an HTML color specifier (e.g. "#FFFFFF" is white).
59	BorderColor(ColorType<T>),
60	/// Sets the style of the line. Note that not all gnuplot terminals support dashed lines. See DashType for the available styles.
61	LineStyle(DashType),
62	/// Sets the transparency of a filled plot. `0.0` - fully transparent, `1.0` - fully opaque. Cannot be used with `FillPattern`.
63	FillAlpha(f64),
64	/// Sets the fill region. See `FillRegionType` for the available regions.
65	FillRegion(FillRegionType),
66	/// Sets the fill pattern. If left at `Auto`, the pattern alternates automatically. Otherwise, see `FillPatternType` for
67	/// the available patterns. Cannot be used with `FillAlpha`.
68	FillPattern(AutoOption<FillPatternType>),
69	/// Sets what an arrowhead looks like
70	ArrowType(ArrowheadType),
71	/// Sets the size of the arrowhead. This is specified in the units of graph (i.e. `1.0` would make the arrow as big as the graph).
72	ArrowSize(f64),
73	/// Width of the whisker bars (as a fraction of the box width) for box and whisker plots.
74	WhiskerBars(f64),
75	/// Which axis pair to use for the plot element.
76	Axes(XAxis, YAxis),
77	/// Box width set per box for box plots: each element is the width of one box
78	BoxWidth(Vec<f64>),
79}
80
81impl<'l> OneWayOwned for PlotOption<&'l str>
82{
83	type Output = PlotOption<String>;
84	fn to_one_way_owned(&self) -> Self::Output
85	{
86		match *self
87		{
88			PointSymbol(v) => PointSymbol(v),
89			PointSize(v) => PointSize(v),
90			Caption(v) => Caption(v.into()),
91			LineWidth(v) => LineWidth(v),
92			Color(ref v) => Color(v.to_one_way_owned()),
93			BorderColor(ref v) => BorderColor(v.to_one_way_owned()),
94			LineStyle(v) => LineStyle(v),
95			FillAlpha(v) => FillAlpha(v),
96			FillRegion(v) => FillRegion(v),
97			ArrowType(v) => ArrowType(v),
98			ArrowSize(v) => ArrowSize(v),
99			WhiskerBars(v) => WhiskerBars(v),
100			FillPattern(v) => FillPattern(v),
101			Axes(x, y) => Axes(x, y),
102			BoxWidth(ref d) => BoxWidth(d.clone()),
103		}
104	}
105}
106
107/// An enumeration of possible X-axes
108#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
109pub enum XAxis
110{
111	X1,
112	X2,
113}
114
115/// An enumeration of possible Y-axes
116#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
117pub enum YAxis
118{
119	Y1,
120	Y2,
121}
122
123/// An enumeration of possible fill regions
124#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
125pub enum FillRegionType
126{
127	Above,
128	Below,
129	Between,
130}
131
132/// An enumeration of possible text and label alignments
133#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
134pub enum AlignType
135{
136	AlignLeft,
137	AlignRight,
138	AlignCenter,
139	AlignTop,
140	AlignBottom,
141}
142
143/// An enumeration of possible dash styles
144#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
145pub enum DashType
146{
147	Solid,
148	SmallDot,
149	Dot,
150	Dash,
151	DotDash,
152	DotDotDash,
153}
154
155impl DashType
156{
157	pub fn to_int(&self) -> i32
158	{
159		match *self
160		{
161			Solid => 1,
162			SmallDot => 0,
163			Dash => 2,
164			Dot => 3,
165			DotDash => 4,
166			DotDotDash => 5,
167		}
168	}
169}
170
171/// An enumeration of possible arrow head styles
172#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
173pub enum ArrowheadType
174{
175	/// An arrow head shaped like a 'V'
176	Open,
177	/// An arrow head shaped like an outlined triangle
178	Closed,
179	/// An arrow head shaped like a filled triangle
180	Filled,
181	/// No arrow head
182	NoArrow,
183}
184
185/// An enumeration of something that can either be fixed (e.g. the maximum of X values),
186/// or automatically determined
187#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
188pub enum AutoOption<T>
189{
190	/// Fixes the value to a specific value
191	Fix(T),
192	/// Lets the value scale automatically
193	Auto,
194}
195
196impl<T> AutoOption<T>
197{
198	/// Same as `Option::map`
199	pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> AutoOption<U>
200	{
201		match self
202		{
203			Fix(v) => Fix(f(v)),
204			Auto => Auto,
205		}
206	}
207}
208
209impl<T: ToString> OneWayOwned for AutoOption<T>
210{
211	type Output = AutoOption<String>;
212	fn to_one_way_owned(&self) -> Self::Output
213	{
214		match self
215		{
216			Fix(v) => Fix(v.to_string()),
217			Auto => Auto,
218		}
219	}
220}
221
222/// An enumeration of label options that control label attributes
223#[derive(Clone, Debug, PartialOrd, PartialEq)]
224pub enum LabelOption<T>
225{
226	/// Sets the offset of the label in characters
227	TextOffset(f64, f64),
228	/// Sets the font of the label. The string specifies the font type (e.g. "Arial") and the number specifies the size (the units are terminal dependent, but are often points)
229	Font(T, f64),
230	/// Sets the color of the label text. The passed string can be a color name
231	/// (e.g. "black" works), or an HTML color specifier (e.g. "#FFFFFF" is white)
232	TextColor(ColorType<T>),
233	/// Rotates the label by a certain number of degrees
234	Rotate(f64),
235	/// Sets the horizontal alignment of the label text (default is left alignment). See AlignType.
236	TextAlign(AlignType),
237	/// Sets a marker for the label. By default no marker is drawn. The valid characters are as follows:
238	///
239	/// * `.` - dot
240	/// * `+` - plus
241	/// * `x` - cross
242	/// * `*` - star
243	/// * `s` - empty square
244	/// * `S` - filled square
245	/// * `o` - empty circle
246	/// * `O` - filled circle
247	/// * `t` - empty triangle
248	/// * `T` - filled triangle
249	/// * `d` - empty del (upside down triangle)
250	/// * `D` - filled del (upside down triangle)
251	/// * `r` - empty rhombus
252	/// * `R` - filled rhombus
253	MarkerSymbol(char),
254	/// Sets the color of the marker. The passed string can be a color name
255	/// (e.g. "black" works), or an HTML color specifier (e.g. "#FFFFFF" is white)
256	MarkerColor(ColorType<T>),
257	/// Sets the size of the marker. The size acts as a multiplier, with 1.0 being the default.
258	MarkerSize(f64),
259}
260
261impl<'l> OneWayOwned for LabelOption<&'l str>
262{
263	type Output = LabelOption<String>;
264	fn to_one_way_owned(&self) -> Self::Output
265	{
266		match self.clone()
267		{
268			TextOffset(v1, v2) => TextOffset(v1, v2),
269			Font(v1, v2) => Font(v1.into(), v2),
270			TextColor(v) => TextColor(v.to_one_way_owned()),
271			Rotate(v) => Rotate(v),
272			TextAlign(v) => TextAlign(v),
273			MarkerSymbol(v) => MarkerSymbol(v),
274			MarkerColor(v) => MarkerColor(v.to_one_way_owned()),
275			MarkerSize(v) => MarkerSize(v),
276		}
277	}
278}
279
280/// An enumeration of axis tick options
281#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
282pub enum TickOption<T>
283{
284	/// Specifies whether the ticks are drawn at the borders of the plot, or on the axis
285	OnAxis(bool),
286	/// If the axes are drawn on the border, this specifies whether to draw the ticks on the opposite border as well
287	Mirror(bool),
288	/// If the axes are drawn on the border, this specifies whether to draw the ticks pointing inward or outward
289	Inward(bool),
290	/// Sets the scale of the minor ticks
291	MinorScale(f64),
292	/// Sets the scale of the major ticks
293	MajorScale(f64),
294	/// Format of the tick labels, e.g. "%.1f ms" will produces labels with "1 ms, 2 ms" etc.
295	Format(T),
296}
297
298impl<'l> OneWayOwned for TickOption<&'l str>
299{
300	type Output = TickOption<String>;
301	fn to_one_way_owned(&self) -> Self::Output
302	{
303		match *self
304		{
305			OnAxis(v) => OnAxis(v),
306			Mirror(v) => Mirror(v),
307			Inward(v) => Inward(v),
308			MinorScale(v) => MinorScale(v),
309			MajorScale(v) => MajorScale(v),
310			Format(v) => Format(v.into()),
311		}
312	}
313}
314
315/// Specifies a type of axis tick
316#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
317pub enum Tick<T, S>
318{
319	/// Major ticks have position and an optional label. The label may have a single C-style format specifier which will be replaced by the location of the tick
320	Major(T, AutoOption<S>),
321	/// Minor ticks only have position
322	Minor(T),
323}
324
325impl<'l, T: Clone, S: ToString> OneWayOwned for Tick<T, S>
326{
327	type Output = Tick<T, String>;
328	fn to_one_way_owned(&self) -> Self::Output
329	{
330		match self
331		{
332			Minor(v) => Minor(v.clone()),
333			Major(v, s) => Major(v.clone(), s.to_one_way_owned()),
334		}
335	}
336}
337
338/// Plot border locations
339#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
340pub enum BorderLocation2D
341{
342	Bottom = 1,
343	Left = 2,
344	Top = 4,
345	Right = 8,
346}
347
348/// Plot margins
349#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
350pub enum MarginSide
351{
352	MarginLeft(f32),
353	MarginRight(f32),
354	MarginTop(f32),
355	MarginBottom(f32),
356}
357
358/// Legend options
359#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
360pub enum LegendOption<T>
361{
362	/// Puts curve samples to the left of the label
363	Reverse,
364	/// Displays legend entries in opposite order
365	Invert,
366	/// Makes the legend horizontal (default is vertical)
367	Horizontal,
368	/// Specifies the location of the legend. The first argument specifies the horizontal
369	/// placement with respect to its position, and the second argument specifies the vertical placement
370	Placement(AlignType, AlignType),
371	/// Title of the legend
372	Title(T),
373	/// Specifies the maximum number of rows, when the legend is vertical
374	MaxRows(u32),
375	/// Specifies the maximum number of columns, when the legend is horizontal
376	MaxCols(u32),
377}
378
379impl<'l> OneWayOwned for LegendOption<&'l str>
380{
381	type Output = LegendOption<String>;
382	fn to_one_way_owned(&self) -> Self::Output
383	{
384		match *self
385		{
386			Reverse => Reverse,
387			Invert => Invert,
388			Horizontal => Horizontal,
389			Placement(v1, v2) => Placement(v1, v2),
390			Title(v) => Title(v.into()),
391			MaxRows(v) => MaxRows(v),
392			MaxCols(v) => MaxCols(v),
393		}
394	}
395}
396
397/// Specifies how the contours are drawn
398#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
399pub enum ContourStyle
400{
401	/// Draw lines between points of equal value
402	Linear,
403	/// Draw somewhat smoother curves between points with equal value.
404	///
405	/// The argument specifies the number of points to use to approximate the
406	/// curve for the final drawing step (clamped to range from 2 to 100).
407	Cubic(u32),
408	/// Draw an even smoother curve, this time approximating the locations of
409	/// points with equal value (clamped to range from 2 to 100).
410	///
411	/// The first argument specifies the number of points to use to approximate
412	/// the curve for the final drawing step. The second argument specifies the
413	/// order of the polynomial (clamped to range from 2 to 10).
414	Spline(u32, u32),
415}
416
417/// Specifies what sort of palette to use
418#[derive(Clone, Debug, PartialOrd, PartialEq)]
419pub enum PaletteType<T>
420{
421	/// Use a gray palette with a specified gamma
422	Gray(f32),
423	/// Use a palette with that uses a predefined formula for each color component.
424	/// Each formula is identified by an integer between [-36, 36]. See gnuplot documentation, or use the pre-defined constants.
425	Formula(i32, i32, i32),
426	/// Use a cube helix palette, with a certain start (in radians), cycles, saturation and gamma.
427	CubeHelix(f32, f32, f32, f32),
428	/// A custom palette
429	/// is specified by a sequence of 4-tuples (with at least two elements). The first
430	/// element is the grayscale value that is mapped to the remaining three elements
431	/// which specify the red, green and blue components of the color.
432	/// The grayscale values must be non-decreasing. All values must range from 0 to 1.
433	Custom(T),
434}
435
436impl<'l> OneWayOwned for PaletteType<&'l [(f32, f32, f32, f32)]>
437{
438	type Output = PaletteType<Vec<(f32, f32, f32, f32)>>;
439	fn to_one_way_owned(&self) -> Self::Output
440	{
441		match *self
442		{
443			Gray(v) => Gray(v),
444			Formula(v1, v2, v3) => Formula(v1, v2, v3),
445			CubeHelix(v1, v2, v3, v4) => CubeHelix(v1, v2, v3, v4),
446			Custom(v) => Custom(v.into()),
447		}
448	}
449}
450
451/// A gray palette
452pub const GRAY: PaletteType<&'static [(f32, f32, f32, f32)]> = Gray(1.0);
453/// Default Gnuplot palette
454pub const COLOR: PaletteType<&'static [(f32, f32, f32, f32)]> = Formula(7, 5, 15);
455/// Classic rainbow palette with terrible perceptual properties
456pub const RAINBOW: PaletteType<&'static [(f32, f32, f32, f32)]> = Formula(33, 13, 10);
457/// A black body palette
458pub const HOT: PaletteType<&'static [(f32, f32, f32, f32)]> = Formula(34, 35, 36);
459/// A nice default for a cube helix
460pub const HELIX: PaletteType<&'static [(f32, f32, f32, f32)]> = CubeHelix(0.5, -0.8, 2.0, 1.0);
461
462impl PaletteType<Vec<(f32, f32, f32, f32)>>
463{
464	pub fn write_out_commands(&self, w: &mut dyn Writer)
465	{
466		match *self
467		{
468			Gray(gamma) =>
469			{
470				assert!(gamma > 0.0, "Gamma must be positive");
471				writeln!(w, "set palette gray gamma {:.12e}", gamma);
472			}
473			Formula(r, g, b) =>
474			{
475				assert!(r >= -36 && r <= 36, "Invalid r formula!");
476				assert!(g >= -36 && g <= 36, "Invalid g formula!");
477				assert!(b >= -36 && b <= 36, "Invalid b formula!");
478				writeln!(w, "set palette rgbformulae {},{},{}", r, g, b);
479			}
480			CubeHelix(start, rev, sat, gamma) =>
481			{
482				assert!(sat >= 0.0, "Saturation must be non-negative");
483				assert!(gamma > 0.0, "Gamma must be positive");
484				writeln!(
485						w,
486						"set palette cubehelix start {:.12e} cycles {:.12e} saturation {:.12e} gamma {:.12e}",
487						start, rev, sat, gamma
488					);
489			}
490			Custom(ref entries) =>
491			{
492				if entries.len() < 2
493				{
494					panic!("Need at least 2 elements in a custom palette");
495				}
496				write!(w, "set palette defined (");
497
498				let mut first = true;
499				let mut old_x = 0.0;
500				for &(x, r, g, b) in entries
501				{
502					if first
503					{
504						old_x = x;
505						first = false;
506					}
507					else
508					{
509						write!(w, ",");
510					}
511					assert!(x >= old_x, "The gray levels must be non-decreasing!");
512					old_x = x;
513
514					write!(w, "{:.12e} {:.12e} {:.12e} {:.12e}", x, r, g, b);
515				}
516				writeln!(w, ")");
517			}
518		}
519	}
520}
521
522/// Gnuplot version identifier. This is used to handle version-specific
523/// features.
524#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
525pub struct GnuplotVersion
526{
527	pub major: i32,
528	pub minor: i32,
529}
530
531/// Fill patterns.
532///
533/// Note that these are not guaranteed to be consistent between terminals,
534/// but the following names appear to be the most common interpretations of
535/// the numerical values of these patterns.
536#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
537pub enum FillPatternType
538{
539	Pattern0 = 0,
540	BigCrosses = 1,
541	SmallCrosses = 2,
542	Pattern3 = 3,
543	BigBackSlashes = 4,
544	BigForwardSlashes = 5,
545	SmallBackSlashes = 6,
546	SmallForwardSlashes = 7,
547	Pattern8 = 8,
548}
549
550/// Multiplot Fill Order Options
551#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
552pub enum MultiplotFillOrder
553{
554	/// "rowsfirst" gnuplot option.
555	RowsFirst,
556	/// "columnfirst" gnuplot option.
557	ColumnsFirst,
558}
559
560/// Multiplot Fill Order Options
561#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
562pub enum MultiplotFillDirection
563{
564	/// "downward" gnuplot option.
565	Downwards,
566	/// "upward" gnuplot option.
567	Upwards,
568}