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}