plotly_patched/scatter.rs
1//! Scatter plot
2
3use crate::common::color::{Color, ColorWrapper};
4use crate::common::{
5 Calendar, Dim, ErrorData, Fill, Font, GroupNorm, HoverInfo, Label, Line, Marker, Mode,
6 Orientation, PlotType, Position, Visible,
7};
8use crate::private;
9use crate::Trace;
10use serde::Serialize;
11
12use crate::private::{
13 copy_iterable_to_vec, to_num_or_string_wrapper, NumOrString, NumOrStringWrapper, TruthyEnum,
14};
15#[cfg(feature = "plotly_ndarray")]
16use ndarray::{Array, Ix1, Ix2};
17#[cfg(feature = "plotly_ndarray")]
18use crate::ndarray::ArrayTraces;
19
20#[derive(Serialize, Clone, Debug)]
21pub struct Scatter<X, Y>
22where
23 X: Serialize + Clone + 'static,
24 Y: Serialize + Clone + 'static,
25{
26 r#type: PlotType,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 name: Option<String>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 visible: Option<TruthyEnum<Visible>>,
31 #[serde(skip_serializing_if = "Option::is_none", rename = "showlegend")]
32 show_legend: Option<bool>,
33 #[serde(skip_serializing_if = "Option::is_none", rename = "legendgroup")]
34 legend_group: Option<String>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 opacity: Option<f64>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 mode: Option<Mode>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 ids: Option<Vec<String>>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 x: Option<Vec<X>>,
43
44 #[serde(skip_serializing_if = "Option::is_none")]
45 x0: Option<NumOrStringWrapper>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 dx: Option<f64>,
48
49 #[serde(skip_serializing_if = "Option::is_none")]
50 y: Option<Vec<Y>>,
51
52 #[serde(skip_serializing_if = "Option::is_none")]
53 y0: Option<NumOrStringWrapper>,
54 #[serde(skip_serializing_if = "Option::is_none")]
55 dy: Option<f64>,
56
57 #[serde(skip_serializing_if = "Option::is_none")]
58 text: Option<Dim<String>>,
59 #[serde(skip_serializing_if = "Option::is_none", rename = "textposition")]
60 text_position: Option<Dim<Position>>,
61 #[serde(skip_serializing_if = "Option::is_none", rename = "texttemplate")]
62 text_template: Option<Dim<String>>,
63 #[serde(skip_serializing_if = "Option::is_none", rename = "hovertext")]
64 hover_text: Option<Dim<String>>,
65 #[serde(skip_serializing_if = "Option::is_none", rename = "hoverinfo")]
66 hover_info: Option<HoverInfo>,
67 #[serde(skip_serializing_if = "Option::is_none", rename = "hovertemplate")]
68 hover_template: Option<Dim<String>>,
69
70 #[serde(skip_serializing_if = "Option::is_none")]
71 meta: Option<NumOrStringWrapper>,
72 #[serde(skip_serializing_if = "Option::is_none")]
73 custom_data: Option<Vec<NumOrStringWrapper>>,
74
75 #[serde(skip_serializing_if = "Option::is_none", rename = "xaxis")]
76 x_axis: Option<String>,
77 #[serde(skip_serializing_if = "Option::is_none", rename = "yaxis")]
78 y_axis: Option<String>,
79 #[serde(skip_serializing_if = "Option::is_none")]
80 orientation: Option<Orientation>,
81 #[serde(skip_serializing_if = "Option::is_none", rename = "groupnorm")]
82 group_norm: Option<GroupNorm>,
83 #[serde(skip_serializing_if = "Option::is_none", rename = "stackgroup")]
84 stack_group: Option<String>,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 marker: Option<Marker>,
87 #[serde(skip_serializing_if = "Option::is_none")]
88 line: Option<Line>,
89 #[serde(skip_serializing_if = "Option::is_none", rename = "textfont")]
90 text_font: Option<Font>,
91 #[serde(skip_serializing_if = "Option::is_none")]
92 error_x: Option<ErrorData>,
93 #[serde(skip_serializing_if = "Option::is_none")]
94 error_y: Option<ErrorData>,
95 #[serde(skip_serializing_if = "Option::is_none", rename = "cliponaxis")]
96 clip_on_axis: Option<bool>,
97 #[serde(skip_serializing_if = "Option::is_none", rename = "connectgaps")]
98 connect_gaps: Option<bool>,
99 #[serde(skip_serializing_if = "Option::is_none")]
100 fill: Option<Fill>,
101 #[serde(skip_serializing_if = "Option::is_none", rename = "fillcolor")]
102 fill_color: Option<ColorWrapper>,
103 #[serde(skip_serializing_if = "Option::is_none", rename = "hoverlabel")]
104 hover_label: Option<Label>,
105 #[serde(skip_serializing_if = "Option::is_none", rename = "hoveron")]
106 hover_on: Option<String>,
107 #[serde(skip_serializing_if = "Option::is_none", rename = "stackgaps")]
108 stack_gaps: Option<String>,
109 #[serde(skip_serializing_if = "Option::is_none", rename = "xcalendar")]
110 x_calendar: Option<Calendar>,
111 #[serde(skip_serializing_if = "Option::is_none", rename = "ycalendar")]
112 y_calendar: Option<Calendar>,
113}
114
115impl<X, Y> Default for Scatter<X, Y>
116where
117 X: Serialize + Clone + 'static,
118 Y: Serialize + Clone + 'static,
119{
120 fn default() -> Self {
121 Scatter {
122 r#type: PlotType::Scatter,
123 name: None,
124 visible: None,
125 show_legend: None,
126 legend_group: None,
127 opacity: None,
128 mode: None,
129 ids: None,
130 x: None,
131 x0: None,
132 dx: None,
133 y: None,
134 y0: None,
135 dy: None,
136 text: None,
137 text_position: None,
138 text_template: None,
139 hover_text: None,
140 hover_info: None,
141 hover_template: None,
142 meta: None,
143 custom_data: None,
144 x_axis: None,
145 y_axis: None,
146 orientation: None,
147 group_norm: None,
148 stack_group: None,
149 marker: None,
150 line: None,
151 text_font: None,
152 error_x: None,
153 error_y: None,
154 clip_on_axis: None,
155 connect_gaps: None,
156 fill: None,
157 fill_color: None,
158 hover_label: None,
159 hover_on: None,
160 stack_gaps: None,
161 x_calendar: None,
162 y_calendar: None,
163 }
164 }
165}
166
167impl<X, Y> Scatter<X, Y>
168where
169 X: Serialize + Clone + 'static,
170 Y: Serialize + Clone + 'static,
171{
172 pub fn new<I, K>(x: I, y: K) -> Box<Self>
173 where
174 I: IntoIterator<Item = X>,
175 K: IntoIterator<Item = Y>,
176 {
177 let x = copy_iterable_to_vec(x);
178 let y = copy_iterable_to_vec(y);
179 Box::new(Scatter {
180 x: Some(x),
181 y: Some(y),
182 r#type: PlotType::Scatter,
183 ..Default::default()
184 })
185 }
186
187 #[cfg(feature = "plotly_ndarray")]
188 pub fn from_array(x: Array<X, Ix1>, y: Array<Y, Ix1>) -> Box<Self> {
189 Box::new(Scatter {
190 x: Some(x.to_vec()),
191 y: Some(y.to_vec()),
192 r#type: PlotType::Scatter,
193 ..Default::default()
194 })
195 }
196
197 /// Produces `Scatter` traces from a 2 dimensional tensor (`traces_matrix`) indexed by `x`. This
198 /// function requires the `ndarray` feature.
199 ///
200 /// # Arguments
201 /// * `x` - One dimensional array (or view) that represents the `x` axis coordinates.
202 /// * `traces_matrix` - Two dimensional array (or view) containing the `y` axis coordinates of
203 /// the traces.
204 /// * `array_traces` - Determines whether the traces are arranged in the matrix over the
205 /// columns (`ArrayTraces::OverColumns`) or over the rows (`ArrayTraces::OverRows`).
206 ///
207 /// # Examples
208 ///
209 /// ```
210 /// use plotly::common::Mode;
211 /// use plotly::{Plot, Scatter, ArrayTraces};
212 /// use ndarray::{Array, Ix1, Ix2};
213 ///
214 /// fn ndarray_to_traces() {
215 /// let n: usize = 11;
216 /// let t: Array<f64, Ix1> = Array::range(0., 10., 10. / n as f64);
217 /// let mut ys: Array<f64, Ix2> = Array::zeros((11, 11));
218 /// let mut count = 0.;
219 /// for mut row in ys.gencolumns_mut() {
220 /// for index in 0..row.len() {
221 /// row[index] = count + (index as f64).powf(2.);
222 /// }
223 /// count += 1.;
224 /// }
225 ///
226 /// let traces = Scatter::default()
227 /// .mode(Mode::LinesMarkers)
228 /// .to_traces(t, ys, ArrayTraces::OverColumns);
229 ///
230 /// let mut plot = Plot::new();
231 /// plot.add_traces(traces);
232 /// plot.show();
233 /// }
234 /// fn main() -> std::io::Result<()> {
235 /// ndarray_to_traces();
236 /// Ok(())
237 /// }
238 /// ```
239 #[cfg(feature = "plotly_ndarray")]
240 pub fn to_traces(
241 &self,
242 x: Array<X, Ix1>,
243 traces_matrix: Array<Y, Ix2>,
244 array_traces: ArrayTraces,
245 ) -> Vec<Box<dyn Trace>> {
246 let mut traces: Vec<Box<dyn Trace>> = Vec::new();
247 let mut trace_vectors = private::trace_vectors_from(traces_matrix, array_traces);
248 trace_vectors.reverse();
249 while !trace_vectors.is_empty() {
250 let mut sc = Box::new(self.clone());
251 sc.x = Some(x.to_vec());
252 let data = trace_vectors.pop();
253 if let Some(d) = data {
254 sc.y = Some(d);
255 traces.push(sc);
256 }
257 }
258
259 traces
260 }
261
262 /// Enables WebGL.
263 pub fn web_gl_mode(mut self, on: bool) -> Box<Self> {
264 self.r#type = if on {
265 PlotType::ScatterGL
266 } else {
267 PlotType::Scatter
268 };
269 Box::new(self)
270 }
271
272 /// Sets the trace name. The trace name appear as the legend item and on hover.
273 pub fn name(mut self, name: &str) -> Box<Self> {
274 self.name = Some(name.to_owned());
275 Box::new(self)
276 }
277
278 /// Determines whether or not this trace is visible. If `Visible::LegendOnly`, the trace is not
279 /// drawn, but can appear as a legend item (provided that the legend itself is visible).
280 pub fn visible(mut self, visible: Visible) -> Box<Self> {
281 self.visible = Some(TruthyEnum { e: visible });
282 Box::new(self)
283 }
284
285 /// Determines whether or not an item corresponding to this trace is shown in the legend.
286 pub fn show_legend(mut self, show_legend: bool) -> Box<Self> {
287 self.show_legend = Some(show_legend);
288 Box::new(self)
289 }
290
291 /// Sets the legend group for this trace. Traces part of the same legend group hide/show at the
292 /// same time when toggling legend items.
293 pub fn legend_group(mut self, legend_group: &str) -> Box<Self> {
294 self.legend_group = Some(legend_group.to_owned());
295 Box::new(self)
296 }
297
298 /// Sets the opacity of the trace.
299 pub fn opacity(mut self, opacity: f64) -> Box<Self> {
300 self.opacity = Some(opacity);
301 Box::new(self)
302 }
303
304 /// Determines the drawing mode for this scatter trace. If the provided `Mode` includes
305 /// "Text" then the `text` elements appear at the coordinates. Otherwise, the `text` elements
306 /// appear on hover. If there are less than 20 points and the trace is not stacked then the
307 /// default is `Mode::LinesMarkers`, otherwise it is `Mode::Lines`.
308 pub fn mode(mut self, mode: Mode) -> Box<Self> {
309 self.mode = Some(mode);
310 Box::new(self)
311 }
312
313 /// Assigns id labels to each datum. These ids for object constancy of data points during
314 /// animation. Should be an array of strings, not numbers or any other type.
315 pub fn ids<S: AsRef<str>>(mut self, ids: Vec<S>) -> Box<Self> {
316 let ids = private::owned_string_vector(ids);
317 self.ids = Some(ids);
318 Box::new(self)
319 }
320
321 /// Alternate to `x`. Builds a linear space of x coordinates. Use with `dx` where `x0` is the
322 /// starting coordinate and `dx` the step.
323 pub fn x0<C: NumOrString>(mut self, x0: C) -> Box<Self> {
324 self.x0 = Some(x0.to_num_or_string());
325 Box::new(self)
326 }
327
328 /// Sets the x coordinate step. See `x0` for more info.
329 pub fn dx(mut self, dx: f64) -> Box<Self> {
330 self.dx = Some(dx);
331 Box::new(self)
332 }
333
334 /// Alternate to `y`. Builds a linear space of y coordinates. Use with `dy` where `y0` is the
335 /// starting coordinate and `dy` the step.
336 pub fn y0<C: NumOrString>(mut self, y0: C) -> Box<Self> {
337 self.y0 = Some(y0.to_num_or_string());
338 Box::new(self)
339 }
340
341 /// Sets the y coordinate step. See `y0` for more info.
342 pub fn dy(mut self, dy: f64) -> Box<Self> {
343 self.dy = Some(dy);
344 Box::new(self)
345 }
346
347 /// Sets text elements associated with each (x,y) pair. If a single string, the same string
348 /// appears over all the data points. If an array of string, the items are mapped in order to
349 /// the this trace's (x,y) coordinates. If the trace `HoverInfo` contains a "text" flag and
350 /// `hover_text` is not set, these elements will be seen in the hover labels.
351 pub fn text(mut self, text: &str) -> Box<Self> {
352 self.text = Some(Dim::Scalar(text.to_owned()));
353 Box::new(self)
354 }
355
356 /// Sets text elements associated with each (x,y) pair. If a single string, the same string
357 /// appears over all the data points. If an array of string, the items are mapped in order to
358 /// the this trace's (x,y) coordinates. If trace `HoverInfo` contains a "text" flag and
359 /// `hover_text` is not set, these elements will be seen in the hover labels.
360 pub fn text_array<S: AsRef<str>>(mut self, text: Vec<S>) -> Box<Self> {
361 let text = private::owned_string_vector(text);
362 self.text = Some(Dim::Vector(text));
363 Box::new(self)
364 }
365
366 /// Sets the positions of the `text` elements with respects to the (x,y) coordinates.
367 pub fn text_position(mut self, text_position: Position) -> Box<Self> {
368 self.text_position = Some(Dim::Scalar(text_position));
369 Box::new(self)
370 }
371
372 /// Sets the positions of the `text` elements with respects to the (x,y) coordinates.
373 pub fn text_position_array(mut self, text_position: Vec<Position>) -> Box<Self> {
374 self.text_position = Some(Dim::Vector(text_position));
375 Box::new(self)
376 }
377
378 /// Template string used for rendering the information text that appear on points. Note that
379 /// this will override `textinfo`. Variables are inserted using %{variable}, for example
380 /// "y: %{y}". Numbers are formatted using d3-format's syntax %{variable:d3-format}, for example
381 /// "Price: %{y:$.2f}". See [format](https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md#d3)
382 /// for details on the formatting syntax. Dates are formatted using d3-time-format's syntax
383 /// %{variable|d3-time-format}, for example "Day: %{2019-01-01|%A}".
384 /// See [format](https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md#format) for details
385 /// on the date formatting syntax. Every attributes that can be specified per-point (the ones
386 /// that are `arrayOk: true`) are available.
387 pub fn text_template(mut self, text_template: &str) -> Box<Self> {
388 self.text_template = Some(Dim::Scalar(text_template.to_owned()));
389 Box::new(self)
390 }
391
392 /// Template string used for rendering the information text that appear on points. Note that
393 /// this will override `textinfo`. Variables are inserted using %{variable}, for example
394 /// "y: %{y}". Numbers are formatted using d3-format's syntax %{variable:d3-format}, for example
395 /// "Price: %{y:$.2f}". See [format](https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md#d3)
396 /// for details on the formatting syntax. Dates are formatted using d3-time-format's syntax
397 /// %{variable|d3-time-format}, for example "Day: %{2019-01-01|%A}".
398 /// See [format](https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md#format) for details
399 /// on the date formatting syntax. Every attributes that can be specified per-point (the ones
400 /// that are `arrayOk: true`) are available.
401 pub fn text_template_array<S: AsRef<str>>(mut self, text_template: Vec<S>) -> Box<Self> {
402 let text_template = private::owned_string_vector(text_template);
403 self.text_template = Some(Dim::Vector(text_template));
404 Box::new(self)
405 }
406
407 /// Sets hover text elements associated with each (x,y) pair. If a single string, the same
408 /// string appears over all the data points. If an array of string, the items are mapped in
409 /// order to the this trace's (x,y) coordinates. To be seen, trace `HoverInfo` must contain a
410 /// "Text" flag.
411 pub fn hover_text(mut self, hover_text: &str) -> Box<Self> {
412 self.hover_text = Some(Dim::Scalar(hover_text.to_owned()));
413 Box::new(self)
414 }
415
416 /// Sets hover text elements associated with each (x,y) pair. If a single string, the same
417 /// string appears over all the data points. If an array of string, the items are mapped in
418 /// order to the this trace's (x,y) coordinates. To be seen, trace `HoverInfo` must contain a
419 /// "Text" flag.
420 pub fn hover_text_array<S: AsRef<str>>(mut self, hover_text: Vec<S>) -> Box<Self> {
421 let hover_text = private::owned_string_vector(hover_text);
422 self.hover_text = Some(Dim::Vector(hover_text));
423 Box::new(self)
424 }
425
426 /// Determines which trace information appear on hover. If `HoverInfo::None` or `HoverInfo::Skip`
427 /// are set, no information is displayed upon hovering. But, if `HoverInfo::None` is set, click
428 /// and hover events are still fired.
429 pub fn hover_info(mut self, hover_info: HoverInfo) -> Box<Self> {
430 self.hover_info = Some(hover_info);
431 Box::new(self)
432 }
433
434 /// Template string used for rendering the information that appear on hover box. Note that this
435 /// will override `HoverInfo`. Variables are inserted using %{variable}, for example "y: %{y}".
436 /// Numbers are formatted using d3-format's syntax %{variable:d3-format}, for example
437 /// "Price: %{y:$.2f}".
438 /// https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md#d3_format for details
439 /// on the formatting syntax. Dates are formatted using d3-time-format's syntax
440 /// %{variable|d3-time-format}, for example "Day: %{2019-01-01|%A}".
441 /// https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md#format for details
442 /// on the date formatting syntax. The variables available in `hovertemplate` are the ones
443 /// emitted as event data described at this link https://plotly.com/javascript/plotlyjs-events/#event-data.
444 /// Additionally, every attributes that can be specified per-point (the ones that are
445 /// `arrayOk: true`) are available. Anything contained in tag `<extra>` is displayed in the
446 /// secondary box, for example "<extra>{fullData.name}</extra>". To hide the secondary box
447 /// completely, use an empty tag `<extra></extra>`.
448 pub fn hover_template(mut self, hover_template: &str) -> Box<Self> {
449 self.hover_template = Some(Dim::Scalar(hover_template.to_owned()));
450 Box::new(self)
451 }
452
453 /// Template string used for rendering the information that appear on hover box. Note that this
454 /// will override `HoverInfo`. Variables are inserted using %{variable}, for example "y: %{y}".
455 /// Numbers are formatted using d3-format's syntax %{variable:d3-format}, for example
456 /// "Price: %{y:$.2f}".
457 /// https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md#d3_format for details
458 /// on the formatting syntax. Dates are formatted using d3-time-format's syntax
459 /// %{variable|d3-time-format}, for example "Day: %{2019-01-01|%A}".
460 /// https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md#format for details
461 /// on the date formatting syntax. The variables available in `hovertemplate` are the ones
462 /// emitted as event data described at this link https://plotly.com/javascript/plotlyjs-events/#event-data.
463 /// Additionally, every attributes that can be specified per-point (the ones that are
464 /// `arrayOk: true`) are available. Anything contained in tag `<extra>` is displayed in the
465 /// secondary box, for example "<extra>{fullData.name}</extra>". To hide the secondary box
466 /// completely, use an empty tag `<extra></extra>`.
467 pub fn hover_template_array<S: AsRef<str>>(mut self, hover_template: Vec<S>) -> Box<Self> {
468 let hover_template = private::owned_string_vector(hover_template);
469 self.hover_template = Some(Dim::Vector(hover_template));
470 Box::new(self)
471 }
472
473 /// Assigns extra meta information associated with this trace that can be used in various text
474 /// attributes. Attributes such as trace `name`, graph, axis and colorbar `title.text`,
475 /// annotation `text` `rangeselector`, `updatemenues` and `sliders` `label` text all support
476 /// `meta`. To access the trace `meta` values in an attribute in the same trace, simply use
477 /// `%{meta[i]}` where `i` is the index or key of the `meta` item in question. To access trace
478 /// `meta` in layout attributes, use `%{data[n[.meta[i]}` where `i` is the index or key of the
479 /// `meta` and `n` is the trace index.
480 pub fn meta<C: NumOrString>(mut self, meta: C) -> Box<Self> {
481 self.meta = Some(meta.to_num_or_string());
482 Box::new(self)
483 }
484
485 /// Assigns extra data each datum. This may be useful when listening to hover, click and
486 /// selection events. Note that, "scatter" traces also appends customdata items in the markers
487 /// DOM elements
488 pub fn custom_data<C: NumOrString>(mut self, custom_data: Vec<C>) -> Box<Self> {
489 let wrapped = to_num_or_string_wrapper(custom_data);
490 self.custom_data = Some(wrapped);
491 Box::new(self)
492 }
493
494 /// Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If "x" (
495 /// the default value), the x coordinates refer to `Layout::x_axis`. If "x2", the x coordinates
496 /// refer to `Layout::x_axis2`, and so on.
497 pub fn x_axis(mut self, axis: &str) -> Box<Self> {
498 self.x_axis = Some(axis.to_owned());
499 Box::new(self)
500 }
501
502 /// Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If "y"
503 /// (the default value), the y coordinates refer to `Layout::y_axis`. If "y2", the y coordinates
504 /// refer to `Layout::y_axis2`, and so on.
505 pub fn y_axis(mut self, axis: &str) -> Box<Self> {
506 self.y_axis = Some(axis.to_owned());
507 Box::new(self)
508 }
509
510 /// Only relevant when `stackgroup` is used, and only the first `orientation` found in the
511 /// `stackgroup` will be used - including if `visible` is "legendonly" but not if it is `false`.
512 /// Sets the stacking direction. With "v" ("h"), the y (x) values of subsequent traces are
513 /// added. Also affects the default value of `fill`.
514 pub fn orientation(mut self, orientation: Orientation) -> Box<Self> {
515 self.orientation = Some(orientation);
516 Box::new(self)
517 }
518
519 /// Only relevant when `stackgroup` is used, and only the first `groupnorm` found in the
520 /// `stackgroup` will be used - including if `visible` is "legendonly" but not if it is `false`.
521 /// Sets the normalization for the sum of this `stackgroup`. With "fraction", the value of each
522 /// trace at each location is divided by the sum of all trace values at that location. "percent"
523 /// is the same but multiplied by 100 to show percentages. If there are multiple subplots, or
524 /// multiple `stackgroup`s on one subplot, each will be normalized within its own set.
525 pub fn group_norm(mut self, group_norm: GroupNorm) -> Box<Self> {
526 self.group_norm = Some(group_norm);
527 Box::new(self)
528 }
529
530 /// Set several scatter traces (on the same subplot) to the same stackgroup in order to add
531 /// their y values (or their x values if `orientation` is "h"). If blank or omitted this trace
532 /// will not be stacked. Stacking also turns `fill` on by default, using "tonexty" ("tonextx")
533 /// if `orientation` is "h" ("v") and sets the default `mode` to "lines" irrespective of point
534 /// count. You can only stack on a numeric (linear or log) axis. Traces in a `stackgroup` will
535 /// only fill to (or be filled to) other traces in the same group. With multiple `stackgroup`s
536 /// or some traces stacked and some not, if fill-linked traces are not already consecutive, the
537 /// later ones will be pushed down in the drawing order.
538 pub fn stack_group(mut self, stack_group: &str) -> Box<Self> {
539 self.stack_group = Some(stack_group.to_owned());
540 Box::new(self)
541 }
542
543 /// Determines how points are displayed and joined.
544 pub fn marker(mut self, marker: Marker) -> Box<Self> {
545 self.marker = Some(marker);
546 Box::new(self)
547 }
548
549 /// Line display properties.
550 pub fn line(mut self, line: Line) -> Box<Self> {
551 self.line = Some(line);
552 Box::new(self)
553 }
554
555 /// Sets the text font.
556 pub fn text_font(mut self, text_font: Font) -> Box<Self> {
557 self.text_font = Some(text_font);
558 Box::new(self)
559 }
560
561 /// x-axis error display properties.
562 pub fn error_x(mut self, error_x: ErrorData) -> Box<Self> {
563 self.error_x = Some(error_x);
564 Box::new(self)
565 }
566
567 /// y-axis error display properties.
568 pub fn error_y(mut self, error_y: ErrorData) -> Box<Self> {
569 self.error_y = Some(error_y);
570 Box::new(self)
571 }
572
573 /// Determines whether or not markers and text nodes are clipped about the subplot axes. To show
574 /// markers and text nodes above axis lines and tick labels, make sure to set `xaxis.layer` and
575 /// `yaxis.layer` to "below traces".
576 pub fn clip_on_axis(mut self, clip_on_axis: bool) -> Box<Self> {
577 self.clip_on_axis = Some(clip_on_axis);
578 Box::new(self)
579 }
580
581 /// Determines whether or not gaps (i.e. {nan} or missing values) in the provided data arrays
582 /// are connected.
583 pub fn connect_gaps(mut self, connect_gaps: bool) -> Box<Self> {
584 self.connect_gaps = Some(connect_gaps);
585 Box::new(self)
586 }
587
588 /// Sets the area to fill with a solid color. Defaults to "none" unless this trace is stacked,
589 /// then it gets "tonexty" ("tonextx") if `orientation` is "v" ("h") Use with `fillcolor` if not
590 /// "none". "tozerox" and "tozeroy" fill to x=0 and y=0 respectively. "tonextx" and "tonexty"
591 /// fill between the endpoints of this trace and the endpoints of the trace before it,
592 /// connecting those endpoints with straight lines (to make a stacked area graph); if there is
593 /// no trace before it, they behave like "tozerox" and "tozeroy". "toself" connects the
594 /// endpoints of the trace (or each segment of the trace if it has gaps) into a closed shape.
595 /// "tonext" fills the space between two traces if one completely encloses the other
596 /// (eg consecutive contour lines), and behaves like "toself" if there is no trace before it.
597 /// "tonext" should not be used if one trace does not enclose the other. Traces in a
598 /// `stackgroup` will only fill to (or be filled to) other traces in the same group. With
599 /// multiple `stackgroup`s or some traces stacked and some not, if fill-linked traces are not
600 /// already consecutive, the later ones will be pushed down in the drawing order.
601 pub fn fill(mut self, fill: Fill) -> Box<Self> {
602 self.fill = Some(fill);
603 Box::new(self)
604 }
605
606 /// Sets the fill color. Defaults to a half-transparent variant of the line color, marker color,
607 /// or marker line color, whichever is available.
608 pub fn fill_color<C: Color>(mut self, fill_color: C) -> Box<Self> {
609 self.fill_color = Some(fill_color.to_color());
610 Box::new(self)
611 }
612
613 /// Properties of label displayed on mouse hover.
614 pub fn hover_label(mut self, hover_label: Label) -> Box<Self> {
615 self.hover_label = Some(hover_label);
616 Box::new(self)
617 }
618
619 /// Do the hover effects highlight individual points (markers or line points) or do they
620 /// highlight filled regions? If the fill is "toself" or "tonext" and there are no markers or
621 /// text, then the default is "fills", otherwise it is "points".
622 pub fn hover_on(mut self, hover_on: &str) -> Box<Self> {
623 self.hover_on = Some(hover_on.to_owned());
624 Box::new(self)
625 }
626
627 /// Only relevant when `stack_group` is used, and only the first `stack_gaps` found in the
628 /// `stackgroup` will be used - including if `visible` is set to `Visible::LegendOnly` but not
629 /// if it is set to `Visible::False`.
630 /// Determines how we handle locations at which other traces in this group have data but this
631 /// one does not. With "infer zero" we insert a zero at these locations. With "interpolate" we
632 /// linearly interpolate between existing values, and extrapolate a constant beyond the existing
633 /// values.
634 pub fn stack_gaps(mut self, stack_gaps: &str) -> Box<Self> {
635 self.stack_gaps = Some(stack_gaps.to_owned());
636 Box::new(self)
637 }
638
639 /// Sets the calendar system to use with `x` date data.
640 pub fn x_calendar(mut self, x_calendar: Calendar) -> Box<Self> {
641 self.x_calendar = Some(x_calendar);
642 Box::new(self)
643 }
644
645 /// Sets the calendar system to use with `y` date data.
646 pub fn y_calendar(mut self, y_calendar: Calendar) -> Box<Self> {
647 self.y_calendar = Some(y_calendar);
648 Box::new(self)
649 }
650}
651
652impl<X, Y> Trace for Scatter<X, Y>
653where
654 X: Serialize + Clone + 'static,
655 Y: Serialize + Clone + 'static,
656{
657 fn serialize(&self) -> String {
658 serde_json::to_string(&self).unwrap()
659 }
660}